| Name | Modified | Size | Downloads / Week |
|---|---|---|---|
| Parent folder | |||
| README.md | 2026-05-06 | 3.3 kB | |
| v6.12.2 source code.tar.gz | 2026-05-06 | 8.8 MB | |
| v6.12.2 source code.zip | 2026-05-06 | 9.8 MB | |
| Totals: 3 Items | 18.7 MB | 0 | |
Notable changes
Security Fixes
This release addresses several security vulnerabilities that could have caused nodes to diverge from consensus with Zebra.
These vulnerabilities were reported privately by white-hat security researchers and handled through coordinated disclosure by Shielded Labs, Zcash Open Development Lab (ZODL), and Zcash Foundation engineers, in coordination with mining pools.
The following vulnerabilities are addressed by this release:
-
The v4 (Sapling) transaction deserializer silently accepted transactions with no Spend descriptions and no Output descriptions but with a non-zero
valueBalanceSapling— the value was discarded during deserialization, so the consensus check that should have rejected such transactions ran against an already-normalized zero and never fired. Zebra rejects this encoding at deserialization time as required by §7.1.2 of the protocol specification, so a malformed transaction that propagated unchanged from a malicious or custom block producer would have caused a consensus split. The malformed encoding is now rejected at deserialization, matching Zebra. -
In NU5 and later, the authorizing data of v5 transactions (transparent input scripts, Sapling and Orchard proofs and signatures) is committed by the header's
hashBlockCommitmentsviahashAuthDataRoot, but not byhashMerkleRoot. An adversary able to mutate authorizing data could submit a "poisoned" block body whosehashMerkleRootvalue matched the honest header but whose contents were inconsistent withhashBlockCommitments. zcashd's previous handling could (a) persist the poisoned body to disk before detecting the mismatch, and (b) on the sidechain path, mark the corresponding headerBLOCK_FAILED_VALID, permanently invalidating an otherwise valid header.
The fix pre-checks hashBlockCommitments in AcceptBlock for active-tip
extensions (rejecting the body before it is written to disk), treats the
remaining sidechain mismatch in ConnectBlock as body-replaceable, and
resets only the affected block-index entries' body state via the new
CBlockIndex::ResetBodyState so that the canonical body can replace the
poisoned one without losing the header. A regression test exercises both
the active-tip and sidechain paths.
-
The v6.12.1 release added a check rejecting Orchard actions whose ephemeral public key
epkencoded the identity point on the Pallas curve, to match the consensus rule in §5.4.9.4 of the protocol specification. That check rejected only the all-zeros identity encoding; it did not reject other 32-byte strings that fail to encode a valid Pallas curve point, namely: -
non-canonical x (x ≥ q_P, the Pallas base field modulus), and
- canonical x in [0, q_P) for which (x³ + 5) is not a quadratic residue mod q_P (so no curve point exists for that x).
Zebra rejects all three categories, so accepting them in zcashd would
have left the same potential consensus split that the v6.12.1 fix was
intended to close. The check has been broadened to require that epk
decodes to a valid non-identity Pallas point, and the regression test
added in v6.12.1 has been extended to cover the additional categories.