Normal behavior: The protocol uses an UpgradeableBeacon so that many BeaconProxy instances share one implementation and can be upgraded in one place. The beacon owner is expected to upgrade only to non-malicious implementations. Stratax proxy owners (position owners) control their own position via onlyOwner (open, unwind, recoverTokens).
Specific issue: Centralized upgradeability via UpgradeableBeacon—the beacon owner can unilaterally upgrade the implementation for all BeaconProxy instances and introduce malicious logic to drain user funds. If the beacon owner key is compromised or malicious (especially if it’s the same key as a position owner), all user positions are at risk. There is no timelock on UpgradeableBeacon upgrades: the beacon owner can upgrade the implementation instantly. A malicious or compromised owner can point to a new implementation that steals or redirects user funds (e.g. sweep tokens, abuse Aave), enabling an immediate rug pull with no on-chain delay for users to exit.
Likelihood:
The beacon is deployed with an EOA or contract as owner; that owner can call upgradeTo at any time. In production the same key may control both the beacon and one or more proxy owners, or the beacon owner key may be compromised.
There is no timelock or delay—the upgrade takes effect in the same transaction as upgradeTo, so users have no on-chain window to exit before the new implementation is active.
Impact:
A malicious or compromised beacon owner can deploy a malicious implementation (e.g. with a sweep() or modified recoverTokens / Aave logic) and call beacon.upgradeTo(maliciousImplementation), causing all proxies to execute the new code and enabling theft of user funds (contract-held tokens and/or Aave positions).
All user positions backed by proxies that use this beacon are at risk in a single upgrade; there is no per-user or per-proxy isolation from the beacon owner’s upgrade power.
The PoC shows that (1) the beacon owner can upgrade the implementation in one transaction with no delay (no timelock), and (2) the upgrade immediately affects all proxies using that beacon. There is no timelock—upgradeTo is a single call that changes the implementation used by every BeaconProxy on the next invocation. Run: forge test --match-contract PoC_BeaconUpgradeNoTimelock -vvv.
Use a timelock (e.g. OpenZeppelin TimelockController) as the beacon owner so that upgradeTo only takes effect after a scheduled delay (e.g. 24–48 hours), giving users time to exit or the community to react. Deployment change: create the beacon with the timelock as owner instead of an EOA.
Alternative: If upgrades are not required, renounce beacon ownership after deployment (beacon.transferOwnership(address(0)) or beacon.renounceOwnership() if available), at the cost of losing the ability to fix bugs via upgrade.
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.