Full Report
Halo2 is a zero-knowledge (ZK) proof framework based on the PLONK protocol that was originally used for Zcash. Circuits, the flow of operations and verification in a ZK proof, are structured as tables. In these tables, each column holds a sequence of values and each row represents a step in the computation. Constraints, or the limits of the circuit, are defined by querying values in these columns at specific offsets, known as Rotations. Each column is encoded as a polynomial over a finite field. Querying a column at a certain Rotation corresponds to evaluating the value at a specific point. Constraints among columns are enforced using gates. The prover commits the columns using polynomial commitment schemes like KZG. The verifier will receive these commitments and verify it for correctness via black magic math. Circuits have multiple columns and gates, resulting in the evaluation of polynomials at multiple commitment openings. To make this efficient, Halo2 uses a multi-point opening technique, allowing for the verifier to batch many queries into a single proof. In practice, they batch the evaluations, compute a linear combination of all values and check a single equation to ensure it's been satisfied. Alright, enough of the math! What's the vulnerability!? The multi-point opening system encodes the data as Commitment,QueryPoint as the key and to a Value. This key isn't unique enough! It's possible for a "query collision" to occur, where two independent queries have the same key, even if their values are expected to be different. In the context of Halo2, the consequence is horrible: one evaluation can silently overwrite the other. This means that it's possible to forge proofs in many situations. From what I can gather, this vulnerability appears to be somewhat theoretical as no live protocols could have been exploited. Regardless, the bug was super cool and entertaining to look at, even though I don't fully understand ZK math.
Analysis Summary
# Vulnerability: Halo2 Multipoint Opening Query Collision
## CVE Details
- **CVE ID:** Not explicitly assigned (disclosed as the "Query Collision Bug")
- **CVSS Score:** N/A (Theoretical/Soundness Issue)
- **CWE:** CWE-440: Expected Behavior Violation / CWE-694: Use of Multiple Proxies with Same Request (related to logic overwriting)
## Affected Systems
- **Products:**
- Zcash `halo2` implementation
- Privacy Scaling Explorations (PSE) `halo2` fork
- Axiom `halo2` fork
- **Versions:** All versions prior to the July 2025 disclosure/patch.
- **Configurations:** Circuits that trigger or allow "contrived" extra queries resulting in duplicate `(Commitment, QueryPoint)` keys within the multipoint opening argument.
## Vulnerability Description
The vulnerability exists in the **SHPLONK multipoint opening argument** used to batch multiple polynomial evaluations into a single proof. To manage these evaluations, the system uses a mapping (key-value store) where the key is a tuple of `(Commitment, QueryPoint)`.
The logic fails to account for non-unique keys. If two independent queries share the same commitment and evaluation point, the mapping implementation causes one evaluation to **silently overwrite** the other. Because the verifier only checks the final aggregated linear combination based on this mapping, a malicious prover can provide a false value for one of the queries. This bypasses the soundness of the PLONK-based constraints, effectively allowing for proof forgery.
## Exploitation
- **Status:** PoC available (demonstrated by ZK/SEC researchers); No known exploitation in production/live protocols.
- **Complexity:** High (Requires deep understanding of ZK polynomial math and manual construction of "contrived" column queries).
- **Attack Vector:** Local (Malicious Prover crafting a fraudulent proof).
## Impact
- **Confidentiality:** None
- **Integrity:** **Critical** (The soundness of the zero-knowledge proof is broken, allowing invalid computations to be verified as valid).
- **Availability:** Low
## Remediation
### Patches
- **Zcash/ECC:** Patched in the main `halo2` repository.
- **PSE (Privacy Scaling Explorations):** Patched in their respective fork.
- **Axiom:** Patched in their respective fork.
*Users should update to the latest crate versions released after July 2025.*
### Workarounds
- No manual workarounds are recommended other than updating the underlying framework library. Developers should ensure their circuits do not allow arbitrary or redundant queries that could trigger collisions if using legacy versions.
## Detection
- **Indicators of Compromise:** Extremely difficult to detect in existing proofs without re-verifying against a patched prover.
- **Detection Methods:** Circuit developers can audit their "Gate" definitions to identify redundant queries to the same column at the same rotation.
## References
- [ZK/SEC Advisory: Uncovering the Query Collision Bug in Halo2](https://blog[.]zksecurity[.]xyz/posts/halo2-query-collision/index[.]html)
- [Zcash Halo2 GitHub](https://github[.]com/zcash/halo2)
- [PSE Halo2 GitHub](https://github[.]com/privacy-scaling-explorations/halo2)