🛡️ GHSA-cwfq-rfcr-8hmp — zebrad
Description
Zebra's Transparent SIGHASH_SINGLE Handling Diverges from zcashd for Corresponding Outputs
# Zebra Transparent SIGHASH_SINGLE Corresponding-Output Handling Diverges From zcashd
Summary
For V5+ transparent spends, Zebra and zcashd disagree on the same consensus rule: SIGHASH_SINGLE must fail when the input index has no corresponding output. zcashd treats this as consensus-invalid under ZIP-244, while Zebra's transparent verification path computes a digest for the missing-output case instead of failing.
The result is a direct block-validity split. A malformed V5 transparent transaction can be accepted by Zebra, retained in Zebra's mempool, selected into Zebra getblocktemplate, mined into a block, and then rejected by zcashd.
Details
Validated code revisions used during analysis:
zcashd:2c63e9aa08cb170b0feb374161bea94720c3e1f5Zebra:a905fa19e3a91c7b4ead331e2709e6dec5db12cb
Scope note:
- earlier triage material grouped pre-V5 and V5 behavior together;
- re-execution on the pinned revisions did not reproduce the claimed pre-V5 / V4 reject-side behavior;
- this advisory therefore covers the V5+ / ZIP-244 variant only.
zcashd side:
- Transparent scripts in blocks are checked through
TransactionSignatureChecker::CheckSig()andSignatureHash(): [zcash/src/script/interpreter.cpp](https://github.com/zcash/zcash/blob/2c63e9aa08cb170b0feb374161bea94720c3e1f5/src/script/interpreter.cpp#L1386-L1407). - In the ZIP-244 branch,
SignatureHash()explicitly throws whenSIGHASH_SINGLEorSIGHASH_SINGLE|ANYONECANPAYis used withnIn >= txTo.vout.size(): [zcash/src/script/interpreter.cpp](https://github.com/zcash/zcash/blob/2c63e9aa08cb170b0feb374161bea94720c3e1f5/src/script/interpreter.cpp#L1221-L1259). CheckSig()catches that exception and returnsfalse, causing the transparent script to fail.
Zebra side:
- V5 transparent inputs route into the same FFI-based transparent script verifier used for block validation: [
zebra/zebra-consensus/src/transaction.rs](https://github.com/ZcashFoundation/zebra/blob/a905fa19e3a91c7b4ead331e2709e6dec5db12cb/zebra-consensus/src/transaction.rs#L989-L1098). Zebraconverts the decoded hash type and asks its Rust sighash engine for a digest without adding the corresponding-output pre-check thatzcashdenforces first: [zebra/zebra-script/src/lib.rs](https://github.com/ZcashFoundation/zebra/blob/a905fa19e3a91c7b4ead331e2709e6dec5db12cb/zebra-script/src/lib.rs#L160-L175), [zebra/zebra-chain/src/primitives/zcash_primitives.rs](https://github.com/ZcashFoundation/zebra/blob/a905fa19e3a91c7b4ead331e2709e6dec5db12cb/zebra-chain/src/primitives/zcash_primitives.rs#L307-L343).Zebraforwards canonicalSIGHASH_SINGLEinto the Rust ZIP-244 implementation.- In that implementation, when
input.index() >= bundle.vout.len(), the code usestransparent_outputs_hash::<TxOut>(&[])instead of erroring: [zcash_primitives/src/transaction/sighash_v5.rs](https://github.com/zcash/librustzcash/blob/c3425f9c3c7f6deb20720bb78b18f35fbbed8edd/zcash_primitives/src/transaction/sighash_v5.rs#L101-L107), [zcash_primitives/src/transaction/sighash_v5.rs](https://github.com/zcash/librustzcash/blob/c3425f9c3c7f6deb20720bb78b18f35fbbed8edd/zcash_primitives/src/transaction/sighash_v5.rs#L131-L139).
Why this is exploitable:
- the malformed transaction only needs fewer transparent outputs than inputs;
- the attacker signs the digest that
Zebracomputes for the missing-output case; Zebrathen sees a valid transparent signature, whilezcashdnever reaches the same digest because it fails first.
Ordinary path viability:
zcashdordinary mempool admission is not the practical trigger path, because the same ZIP-244SignatureHash()checks fail there first: [zcash/src/main.cpp](https://github.com/zcash/zcash/blob/2c63e9aa08cb170b0feb374161bea94720c3e1f5/src/main.cpp#L1981-L1995), [zcash/src/script/interpreter.cpp](https://github.com/zcash/zcash/blob/2c63e9aa08cb170b0feb374161bea94720c3e1f5/src/script/interpreter.cpp#L1221-L1259).Zebraordinary mempool admission is viable becauseZebrauses the same transparent verifier for mempool and block validation and does not have a separate "one output per input" standardness rule here: [zebra/zebra-consensus/src/transaction.rs](https://github.com/ZcashFoundation/zebra/blob/a905fa19e3a91c7b4ead331e2709e6dec5db12cb/zebra-consensus/src/transaction.rs#L414-L519), [zebra/zebrad/src/components/mempool/storage.rs](https://github.com/ZcashFoundation/zebra/blob/a905fa19e3a91c7b4ead331e2709e6dec5db12cb/zebrad/src/components/mempool/storage.rs#L255-L376).Zebrais a block-template producer, so the realistic stock path isZebramempool ->Zebragetblocktemplate-> external miner: [zebra/zebra-rpc/src/methods/types/get_block_template/zip317.rs](https://github.com/ZcashFoundation/zebra/blob/a905fa19e3a91c7b4ead331e2709e6dec5db12cb/zebra-rpc/src/methods/types/get_block_temp
How this vulnerability can be exploited
This issue can be reached over the network, attack complexity is low, an attacker needs no privileges on the target. No user interaction is required. Rated impact: confidentiality none, integrity high, availability none.
Weakness class
GHSA-cwfq-rfcr-8hmp is classified as CWE-354: Improper Validation of Integrity Check Value. A checksum or integrity value is not verified properly, so tampered data passes as intact.
Affected software
GHSA-cwfq-rfcr-8hmp is recorded against 1 package.
- zebrad
Timeline and source
Published on 7 May 2026 and last revised on 21 May 2026. No public exploit is currently recorded for this entry. Record sourced from OSV.
References
Details
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:H/SA:N
Affected Packages
| Software | From version | Fixed in |
|---|---|---|
| zebrad | — | — |
References
Similar Threats
- Unknown CVE-2026-52731
- Unknown CVE-2026-52732
- Unknown CVE-2026-52733
- Unknown CVE-2026-52734
- Unknown CVE-2026-52738
Exploit Protection
Are you running zebrad?
GHSA-cwfq-rfcr-8hmp carries CVSS 9.5 Critical rating. BotEraser checks your installation against this and other known CVE records, and blocks IPs associated with exploit activity.
Check My Site For GHSA-cwfq-rfcr-8hmp →No credit card required · Results in minutes
ⓘ Data Notice: The information presented above has been compiled from publicly available internet sources. Boteraser aggregates this data solely for informational purposes and does not independently classify, evaluate, or endorse any findings about the vulnerabilities listed. The accuracy and completeness of this information is the sole responsibility of the original publishers. Boteraser and its operators accept no liability for any decisions made based on this data.