When rewards are positive in LSTRewardsSplitter.sol, it must be greater than the rewardThreshold() for it to be split amongst the fee recipients. uint256(newRewards) < controller.rewardThreshold().
This check can be bypassed by calling splitRewards(), because the check does not exist there.
In LSTRewardsSplitter.sol, to split the rewards with the fee recipients, the function performUpkeep() will be called. If the rewards is positive, check that is is above controller.rewardThreshold() before calling _splitRewards().
There is another function splitRewards() that does the same thing but does not have the controller.rewardThreshold() check. Fee recipients who want their fees can simply call splitRewards() instead to bypass the threshold check.
Assume threshold is 1 ETH worth, and the rewards are at 0.5 ETH worth. Instead of waiting for the rewards to reach 1 ETH, fee recipients can call splitRewards() to get their rewards immediately.
Mechanism bypass.
Manual Review
It seems that both functions are called in the LSTRewardsSplitterController contract. Consider limiting splitRewards() call to onlyController.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.