zebrad vulnerable to getblocks/getheaders locator CPU amplification via uncapped vector length
Key facts
- Attack vector
- —
- Privileges required
- —
- User interaction
- —
- Attack complexity
- —
- Impact type
- Denial of service
- Confidentiality · integrity · availability
- —
- Fix status
- Fixed
No CVSS vector from any source. Fix status from GitHub. Impact type from CWE-770.
Summary
### Am I affected You are affected if: 1. You run `zebrad` up to and including `v4.4.1`. 2. Your node accepts inbound P2P connections. ### Summary The `read_getblocks` and `read_getheaders` codec paths accepted block locator vectors up to approximately 65,535 entries (the generic `TrustedPreallocate` ceiling derived from `MAX_PROTOCOL_MESSAGE_LEN`), rather than the protocol-specification limit of 101 entries (matching zcashd's `MAX_LOCATOR_SZ`). Each entry in the locator vector triggers a per-hash chain lookup (`HashMap::contains_key` + `RocksDB::contains_hash`) in `find_chain_intersection` on a tokio blocking-pool thread. A single maximally-sized `getblocks` message occupies one blocking-pool thread for approximately 10–65ms. Under sustained load from multiple peers, this can degrade state-read performance for block validation, RPC, and mempool lookups. ### Details The `read_headers` codec path already implements the correct pattern: it reads the CompactSize count, validates against `MAX_HEADERS_PER_MESSAGE = 160` before deserialization, and rejects oversized messages. The `read_getblocks` and `read_getheaders` paths were missing this pre-deserialization count check and instead relied on the generic `block::Hash::max_allocation()` bound, which allows `(MAX_PROTOCOL_MESSAGE_LEN - 1) / 32 = 65,535` hashes. A legitimate block locator is logarithmic in chain length (approximately 30 hashes for the current ~3M-block Zcash chain). Zebra's own send-side cap is `MAX_FIND_BLOCK_HASHES_RESULTS = 500`. The practical impact requires significant attacker bandwidth (approximately 2 MiB per request) and multiple Sybil peers to meaningfully degrade the blocking pool, which limits real-world exploitability. ### Patches Patched in Zebra 4.4.2. The fix caps `block::Hash::max_allocation()` at `MAX_BLOCK_LOCATOR_LENGTH = 101`, matching zcashd's `MAX_LOCATOR_SZ`. This causes the deserializer to reject oversized locators before any allocation or iteration occurs. ### Workarounds No specific workaround is needed. Existing backpressure mechanisms (load shedding, sequential per-peer message processing, connection limits) constrain the practical impact. ### Impact Under sustained load from multiple Sybil peers, oversized locator vectors can occupy blocking-pool threads and degrade state-read performance. The effect is bounded by connection limits and requires significant attacker bandwidth. ### Credit Vulnerability identified by `@dingledropper`, who submitted the fix in [PR #10570](https://github.com/ZcashFoundation/zebra/pull/10570). Downstream CPU/blocking-pool impact analysis contributed by `@ouicate`.
Why it matters now
SSVC decision points
Not available: CISA has not published SSVC decision points for this record.
Affected products
| Vendor | Product | Affected versions | Fixed in | Status | Source |
|---|---|---|---|---|---|
| — | zebrad (crates.io) | before 4.5.0 | 4.5.0 | Patch available | GHSA-443g-gwgp-49x4 |
| — | zebra-chain (crates.io) | before 8.0.0 | 8.0.0 | Patch available | GHSA-443g-gwgp-49x4 |
- zebrad (crates.io) Vendor— Affected before 4.5.0 Fixed in 4.5.0 Patch available GHSA-443g-gwgp-49x4
- zebra-chain (crates.io) Vendor— Affected before 8.0.0 Fixed in 8.0.0 Patch available GHSA-443g-gwgp-49x4
Remediation
- Fix · GHSA-443g-gwgp-49x4 zebrad (crates.io) Fixed in 4.5.0 Advisory →
- Fix · GHSA-443g-gwgp-49x4 zebra-chain (crates.io) Fixed in 8.0.0 Advisory →
Timeline
- 2026-10-03 Threatist record created from GHSA-443g-gwgp-49x4
References
Sources
This product uses the NVD API but is not endorsed or certified by the NVD. Sources and licences