HIGH: withdraw_continuous missing caller authentication — anyone can drain stream balances
Function Affected
withdraw_continuous (L7601) — public, zero require_auth() on caller
Root Cause
withdraw_continuous calls withdraw_from_flow (L2849) with no authentication check on the caller. The internal function only validates withdrawal_amount > 0 and accumulated_balance >= withdrawal_amount. Any caller can drain any stream's accumulated balance.
Attack
- Attacker calls
withdraw_continuous(victim_stream_id, stream_balance)
withdraw_from_flow subtracts withdrawal_amount from flow.accumulated_balance
- Stream balance is zeroed — legitimate provider cannot withdraw their own funds
- Attacker repeats across all streams
Impact
- Fund destruction: Stream
accumulated_balance is reduced to zero for all streams
- Provider lockout: Legitimate providers lose access to their accumulated earnings
- No gain for attacker — pure griefing/DoS, but financial damage to all stream providers is real
Severity
HIGH — per SECURITY.md section 4.1, High = $5K-$10K bounty.
Fix
Add flow.provider.require_auth() before calling withdraw_from_flow.
HIGH: withdraw_continuous missing caller authentication — anyone can drain stream balances
Function Affected
withdraw_continuous(L7601) — public, zerorequire_auth()on callerRoot Cause
withdraw_continuouscallswithdraw_from_flow(L2849) with no authentication check on the caller. The internal function only validateswithdrawal_amount > 0andaccumulated_balance >= withdrawal_amount. Any caller can drain any stream's accumulated balance.Attack
withdraw_continuous(victim_stream_id, stream_balance)withdraw_from_flowsubtractswithdrawal_amountfromflow.accumulated_balanceImpact
accumulated_balanceis reduced to zero for all streamsSeverity
HIGH — per SECURITY.md section 4.1, High = $5K-$10K bounty.
Fix
Add
flow.provider.require_auth()before callingwithdraw_from_flow.