# Admin transfer leaves stale emergency pause authority

accept_admin rotates POOL_ADMIN but never clears EMERGENCY_ADMIN, so a former admin retains authority to pause reserves and halt deployment.

- Payout: Contest reward
- Severity: medium
- Program: K2
- Credited: v12
- Disclosed: 2026-08-20
- Write-up quality: 6/10
- Original: https://code4rena.com/reports/2026-04-k2#m-10
- Library page: https://bugbountylibrary.com/r/c4%3A2026-04-k2%3AM-10
- Tags: domain:web3 impact:dos impact:privesc kind:contest platform:code4rena sev:medium tech:rust technique:source-review vuln:access-control vuln:business-logic

**Target:** Soroban/Rust pool-configurator contract (accept_admin, emergency pause entrypoints)
**Root cause:** initialize sets EMERGENCY_ADMIN equal to the initial POOL_ADMIN, but accept_admin only rotates POOL_ADMIN and upgrade admin, never updating or clearing EMERGENCY_ADMIN. validate_emergency_admin accepts either the stored emergency admin or current pool admin, so the stale address keeps passing checks.
**Steps:**
1. Deploy/initialize PoolConfigurator: EMERGENCY_ADMIN and POOL_ADMIN both set to admin A.
2. Call `accept_admin` to transfer to admin B; POOL_ADMIN and upgrade admin rotate, EMERGENCY_ADMIN stays A.
3. As former admin A, call `pause_reserve_deployment` / `unpause_reserve_deployment` or `reserve::set_reserve_pause`; `validate_emergency_admin` still authorizes A.
4. Observe router-side paused-reserve checks reject supply/withdraw/borrow/repay/liquidation.
**How found:** Code review of the admin handoff flow: noticed initialize anchors EMERGENCY_ADMIN to the initial admin and accept_admin rotates only POOL_ADMIN/upgrade admin, then traced validate_emergency_admin accepting the stored emergency admin to confirm the stale privilege reaches pause entrypoints.
**Exploitation:** A retired or compromised former admin key retains emergency authority indefinitely; it can pause reserves or halt reserve deployment, freezing live markets (supply, withdraw, borrow, repay, liquidation blocked) until the current admin reverses it. No capital or chaining required.
**Insight:** When a contract stores the same privileged address in two roles at init, audit every rotation path for each role separately; a validator that accepts 'role OR current admin' silently preserves the old role holder after handoff.
