Skip to content

SECURITY: the orchestrator beacon is owned by a compromised EOA on all three chains; #324 must not run until it is moved #335

Description

@thedavidmeister

The deploy EOA 0x8E4bdeec7CEB9570D440676345dA1dCe10329f5b (BEACON_INITIAL_OWNER, rainlang.eth) is reported compromised. It currently owns the orchestrator beacon 0xb9DCd744b0413Dff0EDC70A5B229c7aa03734613 on Base, Ethereum and HyperEVM, read from chain:

beacon owner
orchestrator 0xb9DCd744… (all three chains) 0x8e4bdeec… — compromised
V1 fleet beacons e.g. 0x86e93c39… (Base) 0xe70d821f… token-owner Safe — clean

The V1 fleet is unaffected: it moved to the Safe in the 2026-07 MigrateBeaconOwners broadcast. Only the orchestrator beacon is exposed.

What the key can do right now

  • upgradeTo(anything) on the orchestrator beacon, on all three chains, replacing the implementation behind the live instance 0x3A7387a484d87Aa8bBA45E98AAB401Ce4FBF03E2.
  • renounceOwnership(), permanently burning the beacon. This is unrecoverable in place: BeaconProxy fixes its beacon reference at construction, so the live instance cannot be repointed.

What bounds it today, and what removes the bound

The orchestrator instance holds no vault authority yet#324 has not run. An implementation swapped in behind that beacon today can mint and burn nothing.

#324 is exactly what removes that bound. It grants the orchestrator DEPOSIT/WITHDRAW on every production vault, which converts "a compromised key over an inert proxy" into "a compromised key over fleet-wide mint and burn on three chains". #324 must not be authored or signed until the beacon owner is off this EOA.

The fix, and why it is a race

#317 (20260818-migrate-orchestrator-beacon-owner) transfers the beacon to the chain Safe. One transaction per chain, no multisig signing required — the Safe is the recipient, not a signer. It is ready and green.

It must be broadcast by the compromised key, because OZ Ownable.transferOwnership admits no one else. So this is a race against anyone else holding it. Once the transfer lands the EOA has no remaining power over the beacon.

The recovery path is worse than a redeploy

ST0xOrchestratorBeaconSetDeployers constructor hardcodes the initial owner:

iOrchestratorBeacon = new UpgradeableBeacon(
    LibProdDeployCurrent.ST0X_ORCHESTRATOR, LibProdDeployCurrent.BEACON_INITIAL_OWNER
);

That is audited 0.1.30 bytecode, already deployed on all three chains. Deploying a fresh set-deployer from the current artifact would create a new beacon owned by the same compromised key. Recovery from a bricked beacon therefore needs the constant changed, which changes the creation code, which means a new audited artifact — not a redeploy of what exists. It also needs a new instance address, repinning #316s invariants, #324s grants and #334s beacon set (per #326 the existing set-deployer can never produce nonce 2 again).

Order

  1. Broadcast Orchestrator beacon-owner migration to the chain Safe #317 on all three chains, as the EOA, now.
  2. Only then author or sign Cutover bundle: mint/burn to the orchestrator, signer via MINT/BURN #324.
  3. Orchestrator beacon owner is pinned to the hot deploy EOA as permanent expected state, and the timelock migration structurally cannot reach it #333 / Add the orchestrator beacon to the governed beacon set #334 (orchestrator beacon into the governed set) go green once step 1 lands; the pranked-transfer simulation already confirms that.

This also reframes #333: the "hot deploy EOA pinned as permanent expected state" finding is not hygiene, it is a live compromise with no deadline forcing its resolution.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions