Brevis Pico ZKVM — disclosed vulnerability reports and payouts
Every publicly disclosed and closed bug bounty report we hold for Brevis Pico ZKVM, with our own summary of each finding and a link to the original disclosure.
- Reports indexed
- 8
- Total paid
- $0
- Critical
- 0
- Largest payout
- $0
This page collects the 8 closed, publicly disclosed Brevis Pico ZKVM 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 Oracle manipulation, Integer overflow / underflow, Logic error, across Other, 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
- Oracle manipulation findings disclosed against Brevis Pico ZKVM
- Integer overflow / underflow findings disclosed against Brevis Pico ZKVM
- Logic error findings disclosed against Brevis Pico ZKVM
Curated highlights
The largest disclosed payouts in this group, with our own summary of each. Every report links back to the original disclosure.
Brevis Pico ZKVM: Malicious verifier will recover private witness values breaking zero-knowledge property
Brevis Pico, a privacy-preserving zkVM, relies on a fork of the gnark proving library (v0.1.0) that carries CVE-2024-45040: the Groth16 proving system emits Pedersen commitments without blinding factors. Because the BabyBear, KoalaBear, and verifier circuits invoke RangeChecker.Check() (which internally uses these unblinded commitments) whenever the GROTH16 environment variable is not set to 1 — the production default — a verifier who holds a proof can brute-force low-entropy private witnesses by regenerating commitments over candidate values and matching them. The accompanying Go PoC demonstrates recovery of a 10-bit secret from a proof commitment. This directly violates the zero-knowledge privacy guarantee the zkVM advertises, exposing program traces, memory access patterns, and confidential inputs such as keys or merkle leaves. The protocol team acknowledged the finding and fixed it in pull request #61, with the recommended mitigation being an upgrade to gnark 0.11.0.
Brevis Pico ZKVM: Missing `offset` check will cause integer overflow violating ELF specification
The Brevis Pico ZKVM's ELF disassembler, in the `Elf::new()` constructor, computed file offsets for segment loading with an unchecked u32 addition (`offset + i + j`) before casting to usize. Because the addition happens in u32 space, a crafted RISC-V ELF carrying a PT_LOAD segment whose p_offset sits near u32::MAX and whose mem_size drives the loop counters can make the sum wrap around to a small value. The wrapping neither panics nor returns an error, so the code proceeds to read `source_code` at the wrong offset, either out of bounds or from an unintended location. This breaks the guarantee that `Elf::new()` only accepts well-formed ELF binaries, corrupting downstream prover behavior. The protocol team fixed it by switching to checked arithmetic that surfaces an error on overflow, acknowledged in pull request 61.
Brevis Pico ZKVM: `operand_to_check` is not constrained to be a valid word in `eval_ecall`
Brevis Pico, a ZKVM that executes RISC-V guest programs, has a soundness gap in its environment-call path. The FieldWordRangeChecker assumes the argument `operand_to_check` is a valid word, but the `eval_ecall` constraints never constrain that operand to be well-formed, and unlike other chips it is not routed through the ALU lookup that would validate it. A malicious prover can witness invalid limbs — top limb equal to `most_sig_byte_decomp` and limb sum zero — and pass them to any non-halt, non-commit ecall. This lets ecalls accept words that are not genuine u8 words and, because host programs may use ecalls to call SP1 precompiles, the prover can shape ecall behavior and break the ZKVM's soundness guarantees.
Brevis Pico ZKVM: read_write chip does not enforce constraints on opcode selectors
Brevis Pico is a zero-knowledge virtual machine whose RISC-V instruction execution is verified by lookup chips. In the read_write chip, the memory-access lookup commits only to the opcode and the a/b/c operand registers while leaving the opcode-selector flags (op_a_0 and the load/store markers) unconstrained. Because a malicious prover controls all wires during proof generation, it can set those flags freely and thereby prove a memory read or write value that does not match the program semantics. The main program chip enforces these selectors elsewhere, so the gap is specifically the missing cross-table constraint in the read_write chip. This is a soundness-level defect in the verifier, and the protocol team fixed it in PR 61 by constraining the full instruction with opcode selector and op_a_0.
Brevis Pico ZKVM: First chunk having cpu chip is incorrectly checked in convert circuit
Brevis Pico's convert recursion circuit enforces that the first execution chunk must carry a CPU chip, but the guard is evaluated against an already-incremented chunk counter. Because current_chunk is advanced to the 'expected next chunk' before the assert_felt_ne check, the constraint comparing it to one is vacuously satisfied, so a convert proof whose first chunk has no CPU chip is wrongly accepted. That incomplete proof can then be consumed by the combine recursion circuit, where it fails the contains_execution_chunk completeness condition without being caught at the convert stage. The protocol team fixed the flaw by comparing current_chunk - 1 instead, per PR 61.
Brevis Pico ZKVM: wrong sign handling when x == 0 produces non-canonical / out-of-range x = p
Brevis Pico's Ed25519 point-decompression gadget in its ZKVM applies an unconditional field flip (x = p − x) whenever the compressed sign bit is set, with no guard for x == 0 and no canonical reduction. For an input decompressing to x == 0 with sign bit 1, this yields the out-of-range coordinate x = p, violating both the canonical range 0 ≤ x < p and RFC 8032's rule that the sign bit must be zero when x is zero. The same unconditional flip can pick the wrong square root when the recovered root already matches the requested parity, opening encoding malleability and breaking downstream equality or constraint checks that assume canonical in-range coordinates. The protocol team fixed the issue in brevis-network/pico pull request #61.