Advisories for Cargo/Zebra-State package

2026

zebrad has persistent on-disk corruption of Sapling/Orchard subtree roots after chain fork via pop_tip

When pop_tip removes the tip block during a chain fork, stale Sapling and Orchard note commitment subtree root data is retained in the in-memory non-finalized state. When the chain subsequently finalizes, this stale data is written to the persistent RocksDB state. The corrupted subtree root history affects z_getsubtreesbyindex (used by lightwalletd for wallet synchronization) and could affect future chain verification that depends on correct subtree roots.

Zebra: Repeated Non-Finalized Shielded Transaction Aborts Zebra Before Duplicate-Nullifier Rejection

Chain::push in the non-finalized state updates the transaction-location index (tx_loc_by_hash) before it runs the duplicate shielded-nullifier guard. When an invalid child block repeats a shielded transaction from its non-finalized parent, the assert_eq!(prior_pair, None, "transactions must be unique within a single chain") fires before the contextual validation that would cleanly reject the duplicate. Under Zebra's panic = "abort" release profile, this terminates the entire node process. The block should be rejected …

Zebra: Finalized address balance credit-first overflow on consensus-valid blocks

The finalized transparent address balance writer processes all newly-created outputs (credits) before processing spent outputs (debits) within the same block. A consensus-valid block containing a long chain of same-address transparent self-spends can cause the intermediate per-address balance during the credit pass to exceed MAX_MONEY, triggering a panic in the finalized state writer. Because the triggering block is consensus-valid (zcashd accepts it), the panic recurs on restart when the node re-encounters …

Zebra has block suppression via NU5 same-header body poisoning of sent-hash cache

Zebra records a block hash in non_finalized_block_write_sent_hashes when the block is sent to the write task, before contextual validation completes. If validation fails, the hash is not removed. A remote unauthenticated peer can deliver a poisoned block body that shares a header hash with a later valid canonical block. The poisoned body is rejected, but the hash remains cached. When the valid canonical block arrives, Zebra treats it as a …