Batch 6 (9): dolibarr, jitsi-videobridge, zed, tryton, suricata, strawberry, zulip, zesarux, zephyr Batch 7 (15): xonotic (4), xash3d (3), xenia, xtuple, zabbix (2), zathura, zebra, yabause, zephyr-0001 Batch 8 (15): woodpecker (2), wine (4), widelands (3), wesnoth (3), wekan (3) Mix of CWE-407 and CWE-312.
3.5 KiB
Zebra (Zcash Foundation) — CWE-407 Disclosure Brief (zebra-0001)
2026-04-13 · Patch available — awaiting upstream merge
Finding
One O(T×S) defect in Zebra ZIP-317 block template construction. has_direct_dependencies scans the entire Vec<SelectedMempoolTx> to check whether a candidate transaction's dependencies have been selected, producing O(T²) total work for deep dependency chains.
The Defect
zebra-0001 (PATCHED — LOW-MEDIUM): zebra-rpc/src/methods/types/get_block_template/zip317.rs:228
// In has_direct_dependencies() — fires per dependent tx evaluation:
fn has_direct_dependencies(
candidate_tx_deps: Option<&HashSet<transaction::Hash>>,
selected_txs: &Vec<SelectedMempoolTx>,
) -> bool {
// ...
for tx in selected_txs { // O(S) per call
if deps.contains(&tx.transaction.id.mined_id()) {
num_available_deps += 1;
}
if num_available_deps == deps.len() {
return true;
}
}
false
}
selected_txs grows as transactions are added to the block template. Each dependent transaction evaluation scans the entire selected list. In a deep chain topology with T transactions, total work across a block template build reaches O(T²).
Complexity Proof
At T=1000 transactions in a chain dependency topology:
- Defective: ~500,000 comparisons (O(T²/2))
- Fixed: ~3,000 comparisons (O(T×D) where D=3 average deps)
- ~167x op reduction at T=1000, pathological topology.
At typical mainnet conditions (shallow dependency chains), the practical speedup is smaller, but the worst case remains available to any mempool that constructs deep chains.
Impact
Zebra serves as a Zcash full node implementation by the Zcash Foundation. Block template construction runs once per block (~75 seconds on Zcash mainnet). While not a hot path in typical operation, miners constructing templates from mempools with deep transaction dependency chains (long unconfirmed spend chains) hit the quadratic path. The defect also exists in the low-fee transaction selection path, doubling the exposure.
The Fix
Maintain a HashSet<transaction::Hash> of selected transaction IDs alongside the Vec, reducing has_direct_dependencies to O(D) per check:
// Before
fn has_direct_dependencies(
candidate_tx_deps: Option<&HashSet<transaction::Hash>>,
selected_txs: &Vec<SelectedMempoolTx>,
) -> bool { /* O(S) scan */ }
// After
// CWE-407 fix: HashSet for O(D) dependency check instead of O(S) Vec scan.
fn has_direct_dependencies(
candidate_tx_deps: Option<&HashSet<transaction::Hash>>,
selected_tx_ids: &HashSet<transaction::Hash>,
) -> bool {
deps.iter().all(|dep_id| selected_tx_ids.contains(dep_id)) // O(D)
}
Patch
Fix available: defects/zebra-0001/patch/zebra-0001-zip317-dep-check-hashset.patch
Single-file patch on zebra-rpc/src/methods/types/get_block_template/zip317.rs. Adds selected_tx_ids: HashSet parameter, replaces Vec scan with HashSet membership, inserts IDs incrementally.
What We Ask
A patch is ready for review.
- Confirm receipt and assign a GitHub issue reference (ZcashFoundation/zebra).
- Assess severity — quadratic in transaction chain depth during block template construction.
- Coordinate a disclosure date — we target 90 days from first contact.
- We will credit the Zcash Foundation / Zebra team in the public disclosure. Preferred acknowledgment format welcome.
Contact: see cover email. This brief is confidential until coordinated disclosure.