# Zebra v4.4.0 still accepts V5 SIGHASH_SINGLE without a corresponding output

Zebra accepted V5 transactions signed with SIGHASH_SINGLE lacking a matching output, computing a digest over an empty output set, splitting consensus from zcashd.

- Payout: Research
- Severity: critical
- Program: Zebra
- Found by: sangsoo-osec, fivelittleducks
- Disclosed: 2026-05-08
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-pvmv-cwg8-v6c8
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-pvmv-cwg8-v6c8
- Tags: area:web3 domain:web3 impact:dos impact:integrity kind:research platform:ghsa sev:critical tech:rust technique:incomplete-fix technique:source-review vuln:business-logic vuln:crypto

**Target:** Zcash node transparent transaction script verification (FFI sighash callback)
**Root cause:** Zebra's V5 sighash callback forwarded SIGHASH_SINGLE requests with an out-of-range output index to librustzcash, which hashed an empty output set instead of failing, so ZIP-244 §S.2a rule 2 was never enforced.
**Steps:**
1. Craft a V5 transaction with two or more transparent inputs and fewer transparent outputs.
2. Sign an input whose index has no matching vout entry with `SIGHASH_SINGLE` (`0x03`) or `SIGHASH_SINGLE|ANYONECANPAY` (`0x83`) using the digest Zebra computes.
3. Broadcast the transaction or a block containing it to the network.
4. Zebra accepts the tx/block; zcashd rejects both, splitting Zebra nodes from the network.
**How found:** Researchers compared Zebra's V5 sighash callback against zcashd's SignatureHash/CheckSig behavior and noticed the prior fix (GHSA-cwfq-rfcr-8hmp) added only the non-canonical hashtype rule, leaving the missing-output SIGHASH_SINGLE rule unenforced; librustzcash silently hashed an empty output set instead of erroring.
**Exploitation:** Attacker broadcasts a V5 tx (or block) with more transparent inputs than outputs, signing an input at an index with no corresponding output under SIGHASH_SINGLE. Zebra validates the script and accepts, while zcashd raises an exception in SignatureHash and fails CheckSig, causing a consensus split that could enable partitioning and double-spend against affected nodes.
**Escalation:** Embedding the tx in a block extends the split to chain-level fork, enabling network partition and potential double-spend.
**Insight:** When a consensus client delegates sighash computation to a library, audit the library's out-of-range/edge-case behavior against the reference implementation: a library returning a well-defined digest where the spec demands failure is a silent consensus divergence, and prior partial fixes often cover only one of several sibling rules.

