---
title: "GHSA-cwfq-rfcr-8hmp: Zebra's Transparent SIGHASH_SINGLE Handling Diverges from zcashd for Corresponding Outputs"
url: https://erroneo.us/security/ghsa/GHSA-cwfq-rfcr-8hmp/
description: "GHSA-cwfq-rfcr-8hmp (critical, crates.io (Rust)): Zebra's Transparent SIGHASHSINGLE Handling Diverges from zcashd for Corresponding Outputs. Zebra…"
type: advisory
section: "Security Digest"
date_published: 2026-05-07
date_modified: 2026-05-18
publisher: erroneo.us
author: erroneo.us Security Desk
ghsa: "GHSA-cwfq-rfcr-8hmp"
license: All rights reserved. Quote with attribution and a link.
---

# GHSA-cwfq-rfcr-8hmp: Zebra's Transparent SIGHASH_SINGLE Handling Diverges from zcashd for Corresponding Outputs

## Affected packages

- crates.io (Rust) `zebrad` < 4.4.0 → fixed: 4.4.0

## Details

Zebra Transparent SIGHASHSINGLE Corresponding-Output Handling Diverges From zcashd Summary For V5+ transparent spends, Zebra and zcashd disagree on the same consensus rule: SIGHASHSINGLE 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: 2c63e9aa08cb170b0feb374161bea94720c3e1f5 - Zebra: 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() and SignatureHash(): zcash/src/script/interpreter.cpp. - In the ZIP-244 branch, SignatureHash() explicitly throws when SIGHASHSINGLE or SIGHASHSINGLE|ANYONECANPAY is used with nIn >= txTo.vout.size(): zcash/src/script/interpreter.cpp. - CheckSig() catches that exception and returns false, 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. - Zebra converts the decoded hash type and asks its Rust sighash engine for a digest without adding the corresponding-output pre-check that zcashd enforces first:…

## Sources

- [GitHub Advisory GHSA-cwfq-rfcr-8hmp](https://github.com/advisories/GHSA-cwfq-rfcr-8hmp)
- [github.com](https://github.com/ZcashFoundation/zebra/security/advisories/GHSA-cwfq-rfcr-8hmp)
- [github.com](https://github.com/ZcashFoundation/zebra/releases/tag/v4.4.0)

---
Source page: https://erroneo.us/security/ghsa/GHSA-cwfq-rfcr-8hmp/ · Security Digest: https://erroneo.us/security/ · More: https://erroneo.us/llms.txt
