# Jalr imm_sign is unconstrained

Unconstrained imm_sign flag in OpenVM's Jalr circuit lets a malicious prover alter sign extension of the immediate, changing program flow.

- 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.14
- Library page: https://bugbountylibrary.com/r/cantina%3Aopenvm_january2025%3A3.1.14
- Tags: domain:web3 impact:integrity kind:contest platform:cantina sev:high tech:rust technique:source-review vuln:business-logic

**Target:** Jalr opcode ZK circuit (core.rs)
**Root cause:** The imm_sign flag used to sign-extend the 12-bit immediate is never constrained to match the actual high bit of imm, so the prover can freely choose it.
**Steps:**
1. Read jalr/core.rs#L143-L145: `imm_extend_limb = imm_sign * F::from_canonical_u32((1<<16)-1)`
2. Observe imm_sign is not range-checked or tied to imm's high bit
3. Prover sets imm_sign to 0 or 1 arbitrarily, making imm_extend_limb 0 or 0xFFFF
4. Carry assertion still passes, but computed to_pc differs, redirecting control flow
**How found:** Code review of the Jalr circuit's sign-extension logic; noticed the imm_sign flag feeding imm_extend_limb lacked any constraint tying it to imm's high bit.
**Exploitation:** A malicious prover chooses imm_sign freely when generating a Jalr proof, producing a valid proof for a jump target different from the honest instruction semantics, breaking soundness of program flow.
**Insight:** In ZK circuits, every flag that selects between semantic branches (like sign extension) must be constrained against the underlying data; audit auxiliary selector bits, not just the arithmetic.
