# Wormhole Uninitialized Proxy Bugfix Review

Uninitialized Wormhole implementation contract let an attacker become Guardian and selfdestruct the implementation via submitContractUpgrade, bricking the proxy and locking funds.

- Payout: $10,000,000
- Severity: critical
- Program: Wormhole
- Credited: satya0x
- Disclosed: 2022-05-20
- Write-up quality: 8/10
- Original: https://immunefi.com/blog/bug-fix-reviews/wormhole-uninitialized-proxy-bugfix-review/
- Library page: https://bugbountylibrary.com/r/blog%3Aimmunefi-com-blog-bug-fix-reviews-wormhole-uninitialized-proxy-bugfix-review
- Tags: domain:web3 impact:dos impact:funds-loss kind:bounty platform:blog platform:immunefi sev:critical tech:evm tech:solidity technique:chained technique:source-review vuln:access-control vuln:misconfiguration

**Target:** Wormhole core bridge upgradeable proxy / implementation contract on Ethereum
**Root cause:** A prior bugfix reverted the implementation contract's initialization, leaving initialize() callable so anyone could set their own Guardian set. The UUPS-style upgrade path delegatecalls attacker-supplied initialize() code, which can SELFDESTRUCT the implementation.
**Steps:**
1. Call `initialize()` on implementation contract 0x736d2a394f7810c17b3c6fed017d5bc7d60c077d to set an attacker-controlled Guardian set
2. Deploy a malicious implementation contract whose `initialize()` executes `selfdestruct`
3. Call `submitContractUpgrade(bytes _vm)` on the implementation with a message signed by the malicious Guardian encoding the malicious contract address
4. upgradeImplementation() DELEGATECALLs the malicious initialize() in the implementation's context
5. SELFDESTRUCT destroys the implementation contract, leaving the proxy forwarding to an empty address
**How found:** Researcher generalized the known OpenZeppelin UUPS uninitialized implementation vulnerability: since initialize() sets the first caller as owner/Guardian, an uninitialized implementation lets anyone seize upgrade authority and delegatecall selfdestruct code.
**Exploitation:** Attacker first initializes the uninitialized implementation to install a Guardian set they control, then submits a Guardian-signed upgrade message pointing to a malicious contract whose initialize() selfdestructs. The delegatecall executes in the implementation's context, destroying it; the proxy then forwards all calls to a dead address, permanently bricking upgrades and locking user funds.
**Escalation:** Generalized the OpenZeppelin UUPS uninitialized-proxy pattern to Wormhole's Guardian-multisig upgrade mechanism, turning a benign uninitialized state into permanent fund lockup.
**Insight:** Check whether upgradeable implementation contracts (not just proxies) were ever initialized; a reverted/rolled-back initialization leaves initialize() open, and any delegatecall-to-attacker path that reaches SELFDESTRUCT bricks the proxy permanently.
