zkSync — disclosed vulnerability reports and payouts
Every publicly disclosed and closed bug bounty report we hold for zkSync, with our own summary of each finding and a link to the original disclosure.
- Reports indexed
- 4
- Total paid
- $0
- Critical
- 0
- Largest payout
- $0
This page collects the 4 closed, publicly disclosed zkSync reports indexed on Coin Buggie. Nothing here is active or unpatched — every entry was published by the programme or the researcher after remediation.
The findings concentrate in Reentrancy, Access control, Bridge exploit, Logic error, across EVM-Solidity. Reading a single protocol end to end is the fastest way to see which assumptions its codebase repeatedly gets wrong, which is usually a better predictor of where the next finding lives than the category alone.
Use the vulnerability class links below to compare these findings against the same bug class in other protocols.
What reviewers look for
- Reentrancy findings disclosed against zkSync
- Access control findings disclosed against zkSync
- Bridge exploit findings disclosed against zkSync
- Logic error findings disclosed against zkSync
Curated highlights
The largest disclosed payouts in this group, with our own summary of each. Every report links back to the original disclosure.
zkSync: Synchronization Issue Between L1 and L2 Upgrades
zkSync's upgrade mechanism can advance the recorded protocol version even when the corresponding L2 system upgrade fails. When an upgrade is exclusively L2-side, the upgrade transaction hash is persisted on L1, but during batch commitment the hash is cleared unconditionally in Executor::executeBatches regardless of whether the L2 protocol-upgrade transaction (txType 254) actually succeeded. Because the bootloader records success=false rather than reverting the whole program when that transaction fails, L1 treats the upgrade as completed while the L2 system remains unaltered. This breaks the unique-tx-hash/nonce-equals-protocolVersion invariant and forces the owner to schedule a fresh upgrade and wait through the proposal-execution delay to recover, leaving L1 governance state permanently out of sync with the L2 system until then.
zkSync: Governance logic may enter a deadlock
In zkSync's Governance contract, the permission split between the owner and securityCouncil actors creates a deadlock condition: if the owner is compromised no upgrades can ever be scheduled (owner is the sole proposer), and if the securityCouncil is compromised it can spam `cancel` to veto every owner-proposed upgrade, including the `updateSecurityCouncil` action that would remove it — because the owner cannot call `executeInstant` and the proposal delay is intended to be non-zero. The result is that the governance mechanism becomes permanently inoperable, which is economically significant because it freezes the protocol's ability to upgrade or remediate itself. The sponsor confirmed the finding (agreeing medium severity is fair) and described planned escape-hatch and permission-restructuring mitigations.
zkSync: `Mailbox.requestL2Transaction()` checks the deposit limit of `msg.sender` (`L1WethBridge`) instead of the real depositor of weth from L1, as a result, after certain time, nobody will be able to deposit weth anymore from L1
zkSync's L1 WETH deposit flow routes through L1WethBridge and Mailbox.requestL2Transaction, which enforces a per-depositor deposit cap against msg.sender. Because msg.sender at that point is the L1WethBridge contract rather than the actual depositor, the cap is consumed by the bridge address shared by all users, not per-user. Once cumulative deposits reach the configured limit, every subsequent WETH deposit reverts even though individual users remain well under their own limits. This creates a self-inflicted denial-of-service that eventually locks all WETH bridging to L2, with the PoC demonstrating the failure once total deposits cross the cap.
zkSync: `Mul/div` relation should not be enforced when divisor is zero
In the zkSync Era zkEVM circuit, the mul/div opcode handler unconditionally enforces the algebraic relation dividend = quotient*divisor + remainder whenever a div is executed. Under the EraVM specification, division by zero must instead yield zero quotient and zero remainder, so a nonzero dividend with a zero divisor makes the enforced relation unsatisfiable. Any transaction triggering such a div produces circuit state the prover cannot prove, stalling the priority queue — a denial-of-service on the proof pipeline rather than a fund-theft issue. The zkSync team acknowledged the circuit was over-constrained, and the recommended fix is to skip the mul/div relation constraint when the divisor is zero.