Full Report
zkSync Lite is a zkRollup L2 blockchain. The operator submits a proof attesting to the transition from the old root to the new root via state transitions. The L1 does not re-execute every transaction; the L1 just verifies the proof. Practically, this means that any bug that allows an invalid state transition to satisfy the circuit becomes the on-chain truth once proven. zkSync Lite has operations that are processed in chunks. The circuit iterates over these chunks for verification. The first check is for state mutations, such as balances, nonces and such. The middle chunk is for pubdata consistency. The final chunk is done for fee accounting. From these separate locations in code came two definitions of valid: one for mutation validity (chunk 1) and another for tx validity (signatures, timestamps, etc.). This discrepancy in valid is what causes the bug. The function ChangePubKey sets the account's L2s signing key. On the L1, the contract verifies that the pubkey change uses the nonce from the pubdata. pub_nonce equality is NOT checked in the tx validity, but IS checked within the mutation validity. When handling the fees, the validity was checked via tx validity and not both of them. By putting these altogether, it's possible to create a transaction for ChangePubKeyOffchain where the transaction checker believes it's valid but the mutation doesn't believe so. On the fee accrual chunk, the fee accounting adds more fees than it should without increasing the user debit/nonce. In practice, this attack could be repeated with a malicious proof to mint infinite funds in fees. It appears that this was permissioned because of the reliance on the prover/sequencer/operator though. With ZK vulnerabilities, the most common issues are around missing constraints. In this case, it was a control-flow issue with a semantic meaning mismatch that led to the vulnerability. So, the next time a complicated set of operations confuses you, maybe it confused the devs, too!
Analysis Summary
Based on the technical disclosure provided, here is the summary of the vulnerability identified in zkSync Lite.
# Vulnerability: Logic Discrepancy in ChangePubKey Fee Accounting (Minting Fees)
## CVE Details
- **CVE ID:** Not assigned (typically handled via bug bounty disclosure/internal tracking).
- **CVSS Score:** Estimated 8.8 (High) - (CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:N/I:H/A:H)
- **CWE:** CWE-694 (Use of Multiple Proxies), CWE-670 (Always-Incorrect Control Flow Implementation)
## Affected Systems
- **Products:** zkSync Lite (zkRollup L2)
- **Versions:** Versions prior to the fix implemented following the September 2025 report.
- **Configurations:** Systems utilizing the `ChangePubKeyOffchain` operation within the zero-knowledge circuit.
## Vulnerability Description
The vulnerability stems from a semantic mismatch between two different validation logic paths within the zkSync Lite circuit: **Mutation Validity** (handling state changes like balances and nonces) and **Transaction Validity** (handling signatures and timestamps).
zkSync Lite processes operations in chunks. For the `ChangePubKey` operation:
1. **Chunk 1 (Mutation):** Checks if the `pub_nonce` in the public data matches the account's current nonce.
2. **Final Chunk (Fee Accounting):** Verifies if the fee accrual is valid using only **Transaction Validity** checks.
The flaw lies in the fact that `pub_nonce` equality is strictly enforced in Mutation Validity but was omitted from Transaction Validity. An attacker could craft a `ChangePubKeyOffchain` transaction where the Transaction Validity check passes but Mutation Validity fails. Because the fee accounting logic relied solely on the Transaction Validity check, the circuit would credit fees to the operator (the "minting" effect) without successfully completing the state mutation (debiting the user or incrementing the nonce), allowing for repeatable fee extraction.
## Exploitation
- **Status:** PoC disclosed privately via Immunefi; $200,000 bounty awarded. No evidence of exploitation in the wild.
- **Complexity:** High (Requires the ability to generate/submit malicious ZK proofs; currently constrained to the operator/sequencer).
- **Attack Vector:** Network (specifically targeting the L2 rollup operator/sequencer role).
## Impact
- **Confidentiality:** None
- **Integrity:** High (Violation of "Conservation of Value"; ability to mint infinite funds via illegitimate fee accrual).
- **Availability:** High (Potential for state corruption or total loss of funds in the rollup).
## Remediation
### Patches
- The vulnerability was reported in September 2025 and has been addressed by the zkSync team. Organizations running zkSync Lite infrastructure should ensure they are on the latest circuit and contract releases.
### Workarounds
- As this is a core logic error within the ZK circuit, there are no practical workarounds other than upgrading the circuit logic to ensure that fee accounting is constrained by both transaction and mutation validity.
## Detection
- **Indicators of Compromise:** Discrevancies between total fee accruals and the sum of nonces/debits across L2 accounts.
- **Detection Methods:** Auditors can scan ZK circuits for logic branches where fee distribution is decoupled from the successful state mutation (nonce increment) of the sender.
## References
- Ehsan's Disclosure on X: hxxps[://]x[.]com/Ehsan1579/status/2013482485175226811
- Immunefi Bug Bounty Platform: hxxps[://]immunefi[.]com/
- zkSync Lite Documentation: hxxps[://]docs[.]zksync[.]io/lite/