In a stream there are a few actors: The sender (who sends the funds), the recipient (who receives the funds), approved users and unknown users. Some functionalities in the system are reserved for specific actors within a stream. In this case, the withdraw functionality should be available to all, however the funds should only be sent to the recipient. Due to bad checks in the _withdraw function, this could be exploited, or even if the user makes a mistake in the address they pass in.
In the _withdraw function, a to address is passed. The intention that the to should always be the recipient. The code does have an if statement to check that all the right conditions are met, however an approved user can exploit the arbitrary to address, or even make a mistake in which address they put in, and can pass in any address.
Let us consider the following scenario:
A user is approved.
The user calls the withdraw function.
The user passes in a false address as the to address. Could be maliciously or mistakenly.
The withdraw function calls the internal _withdraw.
The if statement does not revert as it needs BOTH conditionals to be true, but it is an approved user, even though the to address conditional does not equal to _ownerOf(streamId).
Funds are transferred to a false address.
Manual Review
Consider not even having an arbitrary to address. Only let it be possible to pass to recipient as the address is already saved in storage:
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.