# diamondCut is not protected in case of governor’s key leakage

zkSync Diamond governor can swap _calldata after proposal, letting a leaked-key attacker front-run execution with malicious calldata, bypassing the timelock notice period.

- Payout: Audit contest
- Severity: medium
- Program: zkSync
- Found by: HE1M
- Disclosed: 2023-01-04
- Write-up quality: 7/10
- Original: https://code4rena.com/reports/2022-10-zksync#m-01
- Library page: https://bugbountylibrary.com/r/c4%3A2022-10-zksync%3AM-01
- Tags: area:web3 domain:web3 impact:privesc kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:access-control vuln:business-logic

**Target:** Diamond proxy upgrade governor (diamondCut/proposeDiamondCut)
**Root cause:** proposeDiamondCut commits facetCuts and _initAddress but not _calldata, so the governor can change _calldata between proposal and execution; the notice period only gates timing, not content.
**Steps:**
1. Governor proposes a diamondCut; only facetCuts and _initAddress are committed, _calldata is left free.
2. Attacker with leaked governor key waits until upgradeNoticePeriod passes (or security council approval), then submits the execute call with malicious _calldata, front-running the legitimate governor.
3. Execution passes `require(approvedBySecurityCouncil || upgradeNoticePeriodPassed, "a6")` and `require(approvedBySecurityCouncil || !diamondStorage.isFrozen, "f3")` with attacker-controlled calldata.
**How found:** Reading proposeDiamondCut noted _calldata is intentionally left free between propose and execute; reasoned that a leaked-key attacker could exploit this freedom to swap calldata at execution time, defeating the notice period.
**Exploitation:** With a leaked governor key, attacker front-runs the governor's execution transaction, injecting malicious _calldata at the last moment so zkSync has no time to pause or react.
**Insight:** When a timelock commits only part of an upgrade (facetCuts/initAddress) but leaves calldata mutable, the timelock protects timing not content; check whether every executed parameter is bound at proposal time.

