MEDIUM: apply_liveness_slash missing caller authentication — griefing attack on stream buffer balances
Function Affected
apply_liveness_slash (L8303) — public, no require_auth() on caller
Root Cause
apply_liveness_slash calls liveness_check_and_slash (L239 in enterprise.rs) with caller-supplied stale_threshold_ledgers. The internal function does NOT verify the caller's identity. The caller controls the threshold parameter.
Attack
- Attacker calls
apply_liveness_slash(stream_id, meter_id, 1) on any active stream
- If the stream's last heartbeat is 1+ ledgers old (very common — heartbeats are periodic),
liveness_check_and_slash triggers
- Buffer balance is slashed proportionally:
slash = buffer_balance * excess / (base + excess)
flow.is_unreliable is set to true, marking the stream as unreliable
- Attacker repeats across all streams for maximum damage
Impact
- Griefing: Anyone can slash ANY stream's
buffer_balance by passing a low stale_threshold_ledgers value
- Reputation damage:
is_unreliable = true marks the stream as untrustworthy
- No gain for attacker — pure griefing/DoS, but costs are real for stream providers
Severity
MEDIUM — per SECURITY.md section 4.1, Medium = $1K-$5K bounty.
Fix
Add flow.provider.require_auth() at the top of apply_liveness_slash, or restrict stale_threshold_ledgers to admin-configured values.
MEDIUM: apply_liveness_slash missing caller authentication — griefing attack on stream buffer balances
Function Affected
apply_liveness_slash(L8303) — public, norequire_auth()on callerRoot Cause
apply_liveness_slashcallsliveness_check_and_slash(L239 in enterprise.rs) with caller-suppliedstale_threshold_ledgers. The internal function does NOT verify the caller's identity. The caller controls the threshold parameter.Attack
apply_liveness_slash(stream_id, meter_id, 1)on any active streamliveness_check_and_slashtriggersslash = buffer_balance * excess / (base + excess)flow.is_unreliableis set totrue, marking the stream as unreliableImpact
buffer_balanceby passing a lowstale_threshold_ledgersvalueis_unreliable = truemarks the stream as untrustworthySeverity
MEDIUM — per SECURITY.md section 4.1, Medium = $1K-$5K bounty.
Fix
Add
flow.provider.require_auth()at the top ofapply_liveness_slash, or restrictstale_threshold_ledgersto admin-configured values.