# Poseidon2 verify batch: Incorporate sibling row can also be first of top level phase, skipping row incorporation

Poseidon2 verify_batch AIR constraint only enforced start_top_level when next row was incorporate_row, letting a malicious prover start with incorporate_sibling and skip row hash verification.

- Payout: Contest reward
- Severity: high
- Program: OpenVM
- Credited: cergyk
- Disclosed: 2025-03-24
- Write-up quality: 7/10
- Original: https://cdn.cantina.xyz/reports/cantina_competition_openvm_january2025.pdf#3.1.10
- Library page: https://bugbountylibrary.com/r/cantina%3Aopenvm_january2025%3A3.1.10
- Tags: domain:web3 impact:integrity kind:contest platform:cantina sev:high tech:rust technique:incomplete-fix technique:source-review vuln:business-logic vuln:signature-replay

**Target:** Poseidon2 verify_batch AIR constraints (zkVM circuit)
**Root cause:** The end-of-phase constraint only implied 'incorporate_row => start_top_level', not forbidding incorporate_sibling as the first row of the top-level phase, so internal bus interactions enforcing opened-value hashing were skipped.
**Steps:**
1. Read poseidon2/air.rs#L109-L112: end constraint asserts next.start_top_level only when next.incorporate_row.
2. Observe internal_bus.interact at air.rs#L465-L476 is gated on incorporate_row, enforcing row_hash correctness.
3. Craft a malicious prover trace where the row after end is incorporate_sibling instead of incorporate_row.
4. The internal bus interaction is skipped, so top-level hashes are supplied directly without proving the row hashed into the leaf.
5. Fix: add `builder.when(end.clone()).assert_zero(next.incorporate_sibling)`.
**How found:** Code review of the AIR end-of-phase constraint; noticed the implication was one-directional (incorporate_row => start_top_level) and did not exclude incorporate_sibling as the first top-level row, then traced the gated internal_bus.interact to confirm the skipped check.
**Exploitation:** A malicious prover constructs a Poseidon2 verify_batch trace beginning the top-level phase with incorporate_sibling, bypassing the internal bus interaction that checks opened values hash correctly into the leaf, and supplies arbitrary top-level hashes accepted by the verifier.
**Insight:** When auditing AIR/constraint systems, check that phase-transition constraints are biconditional or explicitly exclude every alternative row type; a one-way implication leaves sibling/other variants as an unchecked entry point that skips bus interactions.
