Research into practice

Security findings

Selected public reports from work on AI coding agents, Ethereum consensus, Bitcoin implementations, and zero-knowledge circuits. Each entry links to the upstream report or fix.

  1. Qwen Code

    Repeated provider tool-call IDs could execute the same local command more than once. Our report led to an upstream fix that prevents duplicate execution.

    Upstream report / fix
  2. OpenCode

    The CLI could hang after a shell tool call started a detached child process. Our report is covered by the merged fix that bounds post-exit pipe draining.

    Upstream report / fix
  3. Ethereum Consensus (Lighthouse, dynamic-ssz)

    Implementations incorrectly accept any non-zero byte as true (e.g., 0x02), breaking canonical serialization guarantees. Can lead to validator slashing inconsistencies across clients.

    Upstream report / fix
  4. Ethereum Consensus (Lighthouse, Lodestar, ethereum/remerkleable)

    Affects EIP-6800 ExecutionPayload.execution_witness field. SSZ Union types with None variant incorrectly accept trailing garbage bytes, causing different HashTreeRoot computations and immediate consensus splits in block validation.

    Upstream report / fix
  5. Ethereum Consensus (ethereum/remerkleable)

    SSZ implementation fails to enforce strict offset contiguity in variable-length containers. Attackers can inject hidden 'ghost' bytes between data blocks, creating non-canonical encodings that pass validation but hash differently, leading to consensus splits.

    Upstream report / fix
  6. BitVM

    lshift_prevent_overflow assumes helper shifters populate altstack with (N_LIMBS−1) intermediate limbs and unconditionally pulls exactly (N_LIMBS−1) items back, causing stack underflow or silent stack-shape mismatch.

    Upstream report / fix
  7. BitVM

    is_negative / is_positive misclassify when HEAD_OFFSET == 1. is_negative is always true, is_positive is always false.

    Upstream report / fix
  8. rust-bitcoin-m31

    n31_neg computes (-MOD - x) and rewrites only when result equals -(MOD). For x ∈ {-MOD, 0}, returns 0 instead of canonical twisted zero -(MOD).

    Upstream report / fix