Listen to this Post
How the CVE works:
Zebra’s block validator undercounts transparent signature operations (sigops) against the 20000-sigop block limit (MAX_BLOCK_SIGOPS). This allows Zebra to accept blocks that zcashd rejects with bad-blk-sigops, enabling a miner to split the network: Zebra nodes follow the offending chain while zcashd nodes do not. Two distinct undercounts exist. First, coinbase hidden legacy sigops: zcashd’s GetLegacySigOpCount() includes the coinbase input’s scriptSig, but Zebra’s sigops implementation skipped the coinbase input entirely. Up to ~98 sigops (100-byte coinbase script length cap minus height prefix) can be hidden inside the coinbase scriptSig without being charged. Second, aggregate P2SH sigops: zcashd’s GetP2SHSigOpCount() parses each P2SH input’s redeem script with accurate=true and sums those sigops into the block-wide total via ConnectBlock. Zebra computed P2SH sigops only on the mempool-acceptance path (for ZIP-317 weighting) and never accumulated them during block validation. A block whose aggregate redeem-script sigops exceeds 20000 (e.g., 1334 P2SH spends × 15 sigops = 20010) would be accepted by Zebra and rejected by zcashd. The check is per-block, not per-transaction, and any miner can produce such a block. Patched in v4.4.0; no workarounds exist.
dailycve form:
Platform: Zcash Zebra
Version: <=4.3.x
Vulnerability: Sigop undercount
Severity: Medium
date: 2024-03-19
Prediction: Fixed already
What Undercode Say:
Check Zebra version for vulnerability
zebrad --version | grep -E "^zebrad [0-4].([0-3].|4.[0-3])"
Simulate coinbase sigop undercount (conceptual)
echo "scriptSig length 100 bytes can hide ~98 sigops"
Count P2SH sigops in a block
zcash-cli getblock <hash> | jq '.tx[].vin[].scriptSig?.asm' | grep -c "OP_CHECKMULTISIG"
Reproduce aggregate undercount: craft 1334 P2SH tx with 15 sigops each
for i in {1..1334}; do echo "P2SH redeem script with 15 sigops"; done | wc -l
Validate sigops via zcashd debug
zcash-cli verifyblock <blockhash> 2>&1 | grep "bad-blk-sigops"
Exploit:
A malicious miner constructs a block with a coinbase scriptSig containing ~98 hidden sigops (using OP_CHECKSIG within 100-byte limit) and/or includes 1334+ P2SH-spending transactions each with a redeem script that yields 15 sigops (e.g., 15-of-15 multisig). The total sigops exceed 20000 but Zebra counts only non-coinbase legacy sigops and misses P2SH aggregate entirely. The miner broadcasts the block; Zebra nodes accept it and continue building on that chain, while zcashd nodes reject it, causing a persistent fork.
Protection from this CVE
Upgrade to Zebra v4.4.0 or later: https://github.com/ZcashFoundation/zebra/releases/tag/v4.4.0. No configuration workaround exists. As a secondary measure, run a zcashd node alongside Zebra to detect consensus divergence, or enforce strict block validation via external tooling that replicates zcashd’s sigop counting logic.
Impact
Network split between Zebra and zcashd nodes, leading to double-spending risk and chain fragmentation. Miners following the Zebra chain can produce otherwise invalid blocks, and transactions confirmed on one side may be rejected on the other. Zebra nodes become incompatible with the canonical Zcash network, potentially causing financial losses for exchanges, wallets, and miners relying on Zebra for consensus.
🎯Let’s Practice Exploiting & Learn Patching For Free:
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

