The protocol keeps a pre-claim correction window open so the moderator can fix a wrongly flagged CORRUPTED outcome. The root cause is that bad-faith claimCorrupted() is permissionless and sets claimsStarted = true, so any outsider can sweep to recoveryAddress and permanently block a still-valid correction to SURVIVED or good-faith CORRUPTED.
The contract and design doc both present pre-claim re-flagging as a real safety window, not just a theoretical privilege. flagOutcome intentionally allows re-flags until claimsStarted becomes true, and the design doc says the moderator may correct a typo'd outcome or attacker before any participant locks in the wrong distribution. The unit suite encodes the same assumption by proving re-flagging is allowed before any claim succeeds.
That correction window is supposed to stay open until a claimant with an economic stake actually relies on the flagged branch. But claimCorrupted() is permissionless and has no caller entitlement check at all. On the bad-faith branch it only requires outcome == CORRUPTED, then it sweeps the contract's full live balance to recoveryAddress and flips claimsStarted = true.
That means an outsider can capture the moderator's correction window even though the docs say this is not a front-runnable path. The design doc's rejection of that class of issue is explicitly grounded in the idea that a claim is the distribution-locking event and a staker claiming first is exercising a correct outcome, not usurping one. Here the caller need not be a staker, the named attacker, or any beneficiary at all. A pure outsider can choose when the pool becomes irrevocably recovery-routed.
The result is a concrete wrong-beneficiary sequence:
The moderator flags bad-faith CORRUPTED on a terminal-CORRUPTED registry state, but has not yet closed the documented correction window. Before the moderator can re-flag to SURVIVED (out-of-scope breach) or to good-faith CORRUPTED (named whitehat bounty), an outsider calls claimCorrupted(). The outsider receives nothing themselves, but the function sends the full pool to the sponsor-controlled recoveryAddress and permanently prevents the correction because claimsStarted is now true. The unit suite already proves the locking half of this behavior by asserting once claimCorrupted() runs, later re-flagging reverts OutcomeAlreadySet.
I validated both economically distinct branches locally:
the outsider can prevent a later correction to good-faith CORRUPTED, redirecting the full bounty away from the named attacker and into recoveryAddress
the outsider can prevent a later correction to SURVIVED, forcing stakers' principal and bonus into recoveryAddress even though the moderator could still have restored the survivor payout path moments earlier
This is not the same root cause as the already-documented claimExpired races. Those live in the scope-blind auto-resolution backstop and are accepted in the design doc. This issue comes from a different permissionless function, claimCorrupted(), being allowed to become the first irreversible value-moving action during a moderator-sanctioned correction window.
Any outsider can force the full pool onto the recovery branch before the moderator finishes a still-valid correction. On an out-of-scope corruption flag, the outsider causes stakers to lose principal plus bonus to recoveryAddress instead of receiving SURVIVED. On a good-faith corruption correction, the outsider causes the named attacker to lose the full bounty to recoveryAddress. The outsider therefore decides when users lose optionality and irreversibly routes the entire pool to the wrong beneficiary.
Do not let permissionless claimCorrupted() start finality while the moderator's documented pre-claim correction window is still open; require an explicit finalization step before outsider-triggerable recovery sweeps.
Run:
Observed output:
PoC file used:
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.
The contest is complete and the rewards are being distributed.