NRDAX is NullRabbit's registry for the network-boundary and node-resource attack class against decentralised infrastructure. Each technique is a mechanism-defined class of real primitives observed across node implementations, with evidence, instances, and a permanent citable ID.
NRDAX - decentralised infrastructure attack registry
The fixed family taxonomy techniques are classified under.
CVE-2024-52919 (GHSA-qwp9-p9rr-h729): addr flood → CAddrMan 32-bit nIdCount overflow → assertion abort
CVE-2018-3972 (TALOS-2018-0637): Levin array-of-arrays (0x8D) → epee read_ae POD memcpy → memory corruption
The simulateTransaction RPC handler executes the BPF VM synchronously on the calling Tokio worker thread (no spawn_blocking interposed), and because sigVerify defaults off and simulation is gas-free, an attacker can submit CU-maximizing transactions against pre-loaded programs at no cost. Each concurrent request pins a shared executor thread for the full simulation duration, so per-worker throughput degrades proportionally to concurrent request count, exhausting the bounded async worker pool and starving all other RPC handlers sharing it. The fix-class is interposing async offload (spawn_blocking / dedicated thread pool with backpressure) plus request-side CU/cost accounting for simulate calls, not just on-chain compute budgets.
How unauthenticated simulateTransaction requests saturate an Agave RPC node's executor pool
CVE-2026-40092 / GHSA-27w2-87xv-37c6 (nimiq/core-rs-albatross, nimiq/core-rs-albatross before v1.4.0): validator records are published into the libp2p Kademlia DHT (/nimiq/kad/0.0.1) as TaggedSigned<ValidatorRecord> (tag 0x03). With set_record_filtering(FilterBoth) every inbound PUT_VALUE reaches Verifier::verify_validator_record, which calls validator_record.verify() -> TaggedPublicKey::verify for Ed25519, previously `Ed25519Signature::from_bytes(sig).unwrap()`. ed25519_zebra rejects any non-64-byte slice, so a record whose TaggedSignature byte-vector is not 64 bytes panics via unwrap() → remote unauthenticated crash DoS. Fixed in v1.4.0 (PR #3708, commit 807ee8e) (return false instead of unwrap). https://github.com/advisories/GHSA-27w2-87xv-37c6
CVE-2013-5700: empty BIP37 bloom filter → modulo-by-zero in CBloomFilter::Hash() → crash
QUIC-LEAK / CVE-2025-54939: LSQUIC pre-handshake `packet_in` memory leak from coalesced Initial packets (CVSS 7.5 AV:N/AC:L/PR:N/UI:N/A:H, CWE-401+CWE-770; affected LSQUIC < 4.3.1, fixed 4.3.1 / OpenLiteSpeed 1.8.4 / LiteSpeed Web Server 6.3.4). An unauthenticated remote attacker floods UDP datagrams that each coalesce several QUIC v1 Initial packets — the first with a valid DCID, the rest with distinct invalid DCIDs; lsquic frees only the first coalesced packet_in per datagram and leaks (~96 B each) the rest, before any handshake, bypassing every post-handshake limit -> memory grows at ~70% of bandwidth -> OOM. PUBLIC-CVE REPLICATION captured here as the attack wire signature only (loopback UDP mock; no real lsquic endpoint stood up); the mock_leaked_* counters are a wire-side proxy for the pinned server memory.
CVE-2024-35202: blocktxn with txns not committed to the block merkle root → FillBlock called twice → assertion + node exit (Bitcoin Core <25.0)
CVE-2025-46597: cmpctblock declaring >1GB short-ids → 32-bit size-calc overflow
CVE-2024-32972: eth GetBlockHeaders amount=0 → count-1 underflows to UINT64_MAX → bypasses maxHeadersServe → serves all headers to genesis → memory exhaustion (geth <1.13.15)
Count Underflow Header Serving Amplification
How a zero-value GetBlockHeaders request underflows to serve go-ethereum's entire header chain (CVE-2024-32972)
Alien Attack (SlowMist 'peer-pool pollution'): a same-family but DIFFERENT-chain peer completes the chain-agnostic RLPx ECIES handshake + devp2p Hello and is admitted to the eth handshake; the chain check (networkID/genesis) happens only at eth Status, AFTER the full handshake — so an alien (Ethereum mainnet identity vs the target's privnet) forces geth to spend the whole ECIES+Hello handshake before disconnecting on the mismatch. Flooding alien handshakes wastes handshake CPU + occupies connection slots (peer-pool pollution). Class disclosed by SlowMist (first found the Alien Attack); no CVE.
quiche QUIC CRYPTO-frame flood (CVE-2024-1765): flood of QUIC long-header packets each carrying a CRYPTO frame (type 0x06) whose offset escalates by a fixed stride (4096) — leaving the crypto reassembly stream permanently non-contiguous so the receiver retains every out-of-order range — and whose declared length (4096) exceeds the truncated (200-byte) body delivered, so a modest packet rate reserves an unbounded, monotonically-growing crypto-reassembly buffer. Real CVE is post-handshake 1-RTT CRYPTO frames; a loopback mock cannot complete a real TLS 1.3 handshake, so the reassembly-buffer-growth wire signature is modelled on the QUIC long-header CRYPTO surface (frame type + escalating offsets + oversized declared span are the load-bearing artefacts). public-cve-replication — replicated wire signature, not a NullRabbit measurement. Affected quiche <= 0.19.1, 0.20.0; fixed 0.19.2, 0.20.1; CVSS 3.1 5.9 (Moderate); reported by Marten Seemann. https://github.com/cloudflare/quiche/security/advisories/GHSA-78wx-jg4j-5j6g
Crypto Frame Reassembly Buffer Exhaustion
Declare Transaction Compilation CPU Exhaustion
quic-go HTTP/3 QPACK decompression-bomb memory exhaustion (CVE-2025-64702): a flood of QUIC v1 short-header (1-RTT) packets, each carrying a STREAM frame (type 0x0b) on a fresh client bidi stream whose data is an HTTP/3 HEADERS frame (type 0x01) holding a QPACK block: field-section prefix 00 00 (static-only) + 128 Indexed Field Line refs to static index 85 ('content-security-policy: script-src 'none'; object-src 'none'; base-uri 'none'', 76 B) encoded as the 2 bytes 'ff 16' each. Each ref is 2 wire bytes but decodes to a 108-byte field-section entry, so a 258-byte block decodes to 13824 B (~54x, the advisory's ~50x). MODELLED AS A REPEATABLE FLOW: the CVE describes one crafted frame, but the learnable artefact is many such HEADERS frames across many fresh request streams driving SUSTAINED decoder allocation (pre-v0.57.0 there is no SETTINGS_MAX_FIELD_SECTION_SIZE cap, so the expanded field section is allocated per stream without bound). A loopback mock cannot complete a real TLS 1.3 handshake, so the load-bearing wire artefacts modelled are the HEADERS/QPACK frame structure, the static-index density, and the small-on-wire / large-decoded ratio across a stream flood (not real QUIC keys / 1-RTT crypto). public-cve-replication — replicated wire signature, not a NullRabbit measurement. Affected quic-go <= v0.56.0; fixed v0.57.0; severity Moderate (CVSS 5.3); reported by sfoxio (2025-12-11). https://github.com/quic-go/quic-go/security/advisories/GHSA-g754-hx8w-x2g6
CVE-2023-26248 / GHSA-mqr9-hjr8-2m9w: Content Censorship in IPFS via Kademlia DHT abuse. The libp2p Kademlia DHT (go-libp2p-kad-dht (Go; as shipped in go-ipfs/kubo), affected go-libp2p-kad-dht <= 0.20.0 / go-ipfs (kubo) <= 0.18.1) stores/serves a CID's provider record at the peers whose peer IDs have the smallest XOR distance to the CID, with no defence against an attacker manufacturing peer IDs in that neighbourhood. An attacker grinds many Sybil peer IDs closer to a target CID than any honest peer and joins them to the DHT, so the Sybils become the k-closest set for that CID: honest ADD_PROVIDER records land on the Sybils (dropped) and honest GET_PROVIDERS lookups converge on the Sybils, which return no honest provider (only more Sybil CLOSER_PEERS). A small number of strategically placed Sybils makes any content undiscoverable network-wide. Unauthenticated — any peer. Impact: content censorship (NDSS 2024 / arXiv:2307.12212). Protocol Labs deployed detection+mitigation in a later libp2p DHT release.
DNSSEC Validation Bypass Cache Poisoning
CVE-2018-17144: a block whose tx spends one outpoint twice (duplicate inputs); the 0.14 pre-relay optimization (PR#9049) skipped the duplicate-input check → assert(!coin.IsNull()) crash (0.14.x) / supply inflation (0.15.0-0.16.2). Fixed 0.16.3/0.17.0. Patched node rejects bad-txns-inputs-duplicate.
How a missing duplicate-input check in Bitcoin Core let one block crash 0.14.x nodes and silently inflate the supply on 0.15.0-0.16.2 (CVE-2018-17144)
msquic duplicate-transport-parameters VersionInfo leak (CVE-2024-26190): flood of QUIC v1 Initial packets (distinct SCID / new connection each), every Initial carrying a CRYPTO frame (type 0x06) whose body is a TLS ClientHello that repeats the quic_transport_parameters extension (0x0039) 32 times, each extension an encoded transport-parameters blob embedding a version_information TP (id 0x11). Pre-fix msquic re-decoded EACH duplicate into the same struct, allocating VersionInfo (QUIC_POOL_VERSION_INFO) per decode and zeroing without freeing -> one leaked heap buffer per duplicate; total leaked ~= connections x 32. The leak is driven during ClientHello extension parsing (pre-handshake-completion), so a loopback mock that cannot finish a real TLS 1.3 handshake still carries the load-bearing artefacts (duplicated 0x0039 extension + embedded 0x11 TP). public-cve-replication — replicated wire signature, not a NullRabbit measurement. Affected msquic < 2.1.12 (2.1.x), < 2.2.7 (2.2.x), < 2.3.5; fixed 2.1.12, 2.2.7, 2.3.5; CWE-401 (Missing Release of Memory) / CWE-400 (Uncontrolled Resource Consumption); CVSS 3.1 7.5 (High); fix commit d364feeda0dd8b729eca6fef149c1ef98630f0cb. https://github.com/microsoft/msquic/security/advisories/GHSA-2x7m-gf85-3745
Duplicate Transport Parameter Memory Leak
CVE-2023-34451 (GHSA-w24w-wp77-qffm): the mempool's list + map index each other and can desync so the SAME tx appears multiple times in the list and can no longer be fully removed (only a restart clears it) — a MempoolChannel(0x30) Txs message carrying the same tx repeated drives the duplicate-insertion path; flooding identical txs is the wire signature (fixed v0.34.29 / v0.37.2).
cosmos-sdk server/grpc/server.go grpc.NewServer w/o grpc.MaxConcurrentStreams -> grpc-go default effectively unbounded + no SETTINGS_MAX_CONCURRENT_STREAMS signalled; attacker holds many HTTP/2 streams on one conn pinning per-stream state (~7KB) -> ~7GB single-source RSS pin (measured gaiad loopback). Sei fork sets MaxConcurrentStreams(100). COSMOS_SDK_GRPC_STREAM_FLOOD / C11.
Ethash Cache Generation Memory Exhaustion
CVE-2021-42219: go-ethereum v1.10.9 (and earlier pre-Merge ethash-verifying geth) — an unauthenticated remote peer floods a node with an excessive amount of block/header messages; to verify each block's PoW geth must hold the ethash cache for that block's epoch (number // 30000; ~16 MB+ each, generated in consensus/ethash/algorithm.go), so a flood whose announced block numbers span many distinct epochs forces many large cache allocations -> memory exhaustion (the cache for the claimed epoch is generated BEFORE the invalid mixHash/nonce is rejected, so a bogus PoW still triggers the cost). Network-triggered, availability-only (CVSS 7.5, AV:N/A:H). No vendor GHSA; the ethash PoW path was removed at The Merge (Sept 2022), so this is a pre-Merge class. Faithful known-class replication of the flood wire signature; the OOM impact is the CVE's, not reproduced against a live node.
EVM Opcode/Precompile Semantics Divergence
debug_traceCall compute amplification (geth: debug API is DoS-prone, do not expose)
Expensive Debug RPC Compute Amplification
How an exposed debug_traceCall lets one unauthenticated request burn seconds of go-ethereum CPU
Forged Commit Future Height Light Client Attack
CVE-2024-52920 class: oversized GETDATA processing load
CVE-2023-42319: geth <=1.13.4 --http --graphql; a query with N aliased logs(filter:{fromBlock:0}) ops -> unbounded per-alias full-chain scan -> memory blowup
go-ethereum#32344 (geth graphql): a single unauthenticated HTTP POST to /graphql carrying a deeply-nested query `{block{ommers{ommers{...}}}}` is parsed with unbounded nesting depth by graph-gophers/graphql-go; a sufficiently deep query (~1e6 levels) drives recursive-descent parsing past Go's 1 GiB goroutine-stack limit -> `fatal error: stack overflow` -> the geth process crashes (remote DoS). Verified live vs a pre-fix geth (commit dffa1f51): depth 1e6 kills the node. Fixed by graphql.MaxDepth(20). https://github.com/ethereum/go-ethereum/pull/32344
GraphQL Nested Query Depth CPU Exhaustion
NullRabbit measurement (gRPC/h2 multiplex DoS).
How unbounded HTTP/2 concurrent streams let one TCP connection OOM-kill an IOTA node's public gRPC server
IC quic_transport half-open QUIC handshake memory pin (IC_QUIC_HALFOPEN_PIN): a burst of QUIC v1 Initial packets (distinct SCID each) whose CRYPTO frame declares a large TLS handshake length (4096) but delivers a truncated ClientHello (~200 B) leaves rustls 'incomplete, waiting', so each `Connecting` future lives to the pre-handshake timeout pinning ~100 KiB/conn. No Retry (EndpointConfig::default()), no per-IP UDP cap, mTLS only after state is committed. Measured on the real replica (release-2026-05-29_04-44-base, commit a47e543, 2026-06-02): n=200 -> +25.5 MiB (~128 KiB/conn), n=1000 -> +129 MiB (~132 KiB/conn), n=3000 -> +278 MiB (abs 420 MiB, ~95 KiB/conn); across 12,200 total connections ZERO were rejected at admission. MEDIUM/5.9 (bounded only by IC's default-deny firewall + 512 GiB replica RAM, not by any transport control). NullRabbit measurement; chains/ic/findings/IC_QUIC_HALFOPEN_PIN.
How an unauthenticated TLS half-open flood pins rippled's memory and crashes it under low file-descriptor limits
Neodyme ND-FD1-MD-02: QUIC INITIAL flood → per-handshake x25519 + ed25519 sign-tile CPU exhaustion (compute-bound, distinct from the connection-slot flood)
CVE-2025-24883: RLPx auth with an all-zero (off-curve) EC pubkey — geth <1.14.13 skips the secp256k1 point-validity check → handshake crypto crash (fixed 159fb1a)
Handshake Crypto Validation Bypass Crash
CVE-2015-3641: header length field pre-allocates the receive buffer before the body → per-connection OOM
The defect is geth's --http.vhosts allowlist treating an empty/absent Host header as implicitly trusted rather than explicitly denying it, combined with an HAProxy h2->h1 downgrade path that forwards HTTP/2 requests with an empty :authority as an empty Host instead of rejecting or filling it. An attacker with raw-h2 capability sends a request with :authority="" through the HAProxy front; HAProxy forwards it as empty Host while a normal forbidden hostname would be rejected with 403. The measurable effect is a 200 response bypassing the vhost/anti-DNS-rebinding allowlist, granting access that the Host-based authorization was meant to block.
Bypassing go-ethereum's --http.vhosts host allowlist with an empty Host, forged by an HAProxy HTTP/2→1.1 downgrade
CVE-2025-8671 "MadeYouReset" (CVE-2025-55163 / GHSA-prj3-ccx8-p6x4 / VU#767506): an unauthenticated attacker opens an HTTP/2 stream (HEADERS, END_STREAM — a complete request) and then sends a protocol-valid-but-misused control frame — this driver uses WINDOW_UPDATE with a flow-control increment of 0 (a stream error PROTOCOL_ERROR per RFC 9113 §6.9.1) — which forces the SERVER to emit RST_STREAM. Because a reset stream is immediately no longer counted as active, the server's MAX_CONCURRENT_STREAMS ceiling (typ. 100) is never reached, yet the backend has already been handed the request and keeps processing it. Repeating the HEADERS+WINDOW_UPDATE(0) cycle floods the server with unbounded concurrent backend work -> memory/CPU exhaustion -> OOM / CPU-pin -> DoS (Tomcat manifests as OutOfMemoryError). This is DISTINCT from CVE-2023-44487 HTTP/2 Rapid Reset: there the CLIENT sends RST_STREAM, so the reset frames are inbound and rate-limitable; here the RST_STREAM is SERVER-emitted (outbound), so the post-CVE-2023-44487 client-side rapid-reset mitigations do not apply. Faithful known-class replication of the MadeYouReset wire signature (HEADERS+END_STREAM, then WINDOW_UPDATE with a zero increment, then a server-emitted RST_STREAM); the OOM/CPU impact is the CVE's, not reproduced against a live server. source_class=public-cve-replication. Distinct wire signature from the sibling rapid-reset drivers (walrus_http2_rapid_reset / substrate_h2_rapid_reset), which are CLIENT-emitted RST.
CVE-2023-26964 (RUSTSEC-2023-0034): the Rust h2 crate < 0.3.17 does not release stream memory immediately on RST_STREAM and — pre-0.3.17 — has NO bound on streams in the pending-accept-but-remotely-reset state. An unauthenticated attacker cycles HEADERS(open stream)->RST_STREAM(cancel) faster than the application accepts requests off the queue; the queue grows unbounded -> excessive memory + CPU -> OOM (HTTP/2 Rapid Reset, CVE-2023-44487 class). Substrate/polkadot consumed h2 0.3.16 (indirect dep via hyper) on the node JSON-RPC HTTP server (jsonrpsee) and the prometheus monitoring endpoint until paritytech/substrate#13915 bumped it to 0.3.17. The fix (hyperium/h2#668) ADDS max_pending_accept_reset_streams and, on hitting the limit, sends GOAWAY(ENHANCE_YOUR_CALM) and errors the connection — behaviour the vulnerable versions lack, so a pre-0.3.17 server never issues GOAWAY. Network-triggered, availability-only (CVSS 7.5, AV:N/A:H). Faithful known-class replication of the HEADERS+RST_STREAM rapid-reset wire signature; the OOM impact is the CVE's, not reproduced against a live node. source_class=public-cve-replication. Distinct target from walrus_http2_rapid_reset (which is a walrus config disabling an EXISTING h2 limit; here the crate itself has no limit).
Incomplete Packet Timer Overflow CPU Burn
Integer Overflow Decompression Infinite Loop
CVE-2026-34219 (+CVE-2026-33040): gossipsub ControlPrune backoff≈u64::MAX → Instant/Duration overflow panic
How a single crafted gossipsub PRUNE backoff value panics rust-libp2p nodes via an Instant overflow (CVE-2026-34219)
CVE-2021-3121 (gogoproto 'skippy peanut butter'): unknown length-delimited field with a negative-length varint → pre-1.3.2 skip code does iNdEx+=length with no length<0 check → index out of bounds → panic in the cosmos-sdk tx decoder, pre-signature-validation
CVE-2024-52915: INV with 50k items → 50k getheaders replies / send-buffer blowup
CVE-2026-41584 (GHSA-452v-w3gx-72wg): a V5/NU5 tx whose Orchard action rk is the IDENTITY point [0x00;32] — a canonical point the spec allows, so it passes parse + hash() — but Orchard proof verification extracts the identity's affine coords and .unwrap()s (circuit.rs Instance::to_halo2_instance) → PANIC. Single unauth P2P tx crashes the node in verify. Fixed v4.3.1 / zebra-chain 6.0.2.
CVE-2025-54605: flood of PoW-invalid blocks logged unconditionally → log/disk fill
CVE-2025-46598: non-standard tx with many legacy-sighash inputs → quadratic validation CPU, no peer penalty
CertiK Skyfall: Publish RPC disassembles a malformed Move module (empty code_unit) → index panic → RPC crash
GHSA-hrhf-2vcr-ghch (ASA-2025-003): a BitArray whose declared Bits does not match its Elems count (len(Elems) != ceil(Bits/64)) is processed in an invalid state and gossiped to peers before validation → network halt (VoteSetBits channel 0x23; fixed v0.38.19 / v0.37.16).
Malformed Field Gossip Before Validation
CVE-2026-41585 (GHSA-29x4-r6jv-ff4w): Zebra's JSON-RPC HTTP middleware treated a failure to read the incoming HTTP request body as an unrecoverable error, aborting the process instead of returning an error response. A client that opens the RPC HTTP connection, sends headers (Content-Length promising the full JSON-RPC body) plus only a PARTIAL body, then RSTs the socket mid-transfer (premature disconnect) crashes the node; an authenticated attacker repeats it to hold the node in a crash/restart loop -> availability DoS. Requires a client that can pass cookie auth (on by default). Affected: zebrad 2.2.0 .. <4.3.1 (through 4.3.0), zebra-rpc 1.0.0-beta.45 .. <6.0.2 (through 6.0.1). Fixed: zebrad 4.3.1 / zebra-rpc 6.0.2 (body-read failure now propagated as an ordinary error response).
CVE-2026-22868 (CVSS 7.5): a batch of EIP-4844 type-3 blob txs announced then delivered (PooledTransactions) with structurally-valid KZG sidecars whose commitment/proof (over blob A) mismatch the carried blob (B) — geth <1.16.8 runs the full KZG proof pairing on EVERY tx in the batch before any validity check, so a malicious peer forces per-tx cryptographic verification → CPU exhaustion/crash. Fixed abeb78c (break + disconnect on first KZG failure; core/txpool/validation.go + eth/fetcher/tx_fetcher.go)
CVE-2022-23328 (go-ethereum, CVSS 7.5, all versions <1.10.13): an attacker node sends 5120 PENDING high-gas-price txns from ONE account that each fully spend the account's FULL BALANCE, in one eth Transactions (0x02→0x12) message. The high gas price purges the victim's pending mempool, and the 5120 same-account spend-all txns then occupy the pool → new txns can't enter → DoS. Sibling of CVE-2022-23327 (future-nonce flood) but a distinct pending-set spend-all vector. Fixed geth 1.10.13.
Mempool Sender Spoofing Resource Exhaustion
GHSA-x5vx-95h7-rv4p (cosmos-sdk <=0.47.15/<=0.50.11): x/group PercentageDecisionPolicy.Allow does yesCount.Quo(totalPower) with no totalPower==0 guard; a proposal on a group whose weight is driven to 0 → division-by-zero panic during FinalizeBlock → CONSENSUS FAILURE / chain halt
CertiK Skyfall HamsterWheel: crafted-CFG Move module defeats id_leak_verifier fixpoint → infinite re-analysis → CPU halt
CVE-2020-26264: a crafted LES GetProofsV2 storage-proof request (non-empty AccKey for a non-existent account) dereferences a nil account trie in the les server's GetProofsV2 handler → panic/crash (geth <1.9.25). Delivered after a real LES Status handshake to a synced --light.serve node; a patched server serves it safely (ProofsV2 reply) — the malicious request reaches the exact vulnerable handler.
Nondeterministic Execution Consensus Split
quiche optimistic-ACK congestion-window growth (CVE-2025-4820): a QUIC peer completes a handshake, initiates a congestion-controlled transfer toward itself, then sends ACK frames (type 0x02 / 0x03) acknowledging packet-number ranges AHEAD of what the sender has actually sent — pacing the artificial ACKs so the server sees a very low RTT and grows its CWND without bound, admitting more bytes in flight than the path supports (availability / bandwidth amplification). CVSS 3.1 = 5.3 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L). Affected quiche < 0.24.4; fixed 0.24.4. public-cve-replication — wire signature only (loopback mock plays the sender; this driver plays the attacker receiver emitting the optimistic/forward ACKs). The CWND-growth impact is a property of the vulnerable congestion controller, recorded here as advisory facts, not reproduced.
Optimistic ACK Congestion Window Manipulation
CVE-2024-52914: orphan-tx re-resolution O(outputs × 100 orphans) of expensive txs → multi-hour CPU stall
quinn-proto out-of-order stream reassembly memory exhaustion (GHSA-4w2j-m93h-cj5j / RUSTSEC-2026-0185, CVSS 7.5 AV:N/AC:L/PR:N/UI:N/A:H, CWE-770; affected quinn-proto < 0.11.15, fixed 0.11.15). An unauthenticated remote peer floods one QUIC connection with small STREAM frames at escalating non-contiguous offsets and never sends offset 0, so the receiver's `Assembler` buffers every gapped fragment as a distinct un-coalescible entry that is never deliverable -> the reassembly buffer's per-fragment overhead grows unbounded (memory exhaustion / DoS). PUBLIC-CVE REPLICATION captured here as the attack wire signature only (loopback UDP mock; no real quinn endpoint stood up); the mock_retained_* counters are a wire-side proxy for the pinned receiver memory.
CometBFT BlocksyncChannel(0x40) oversized BlockResponse (up to 9000 CommitSigs, ~900KB): the Block decode + ValidateBasic at https://github.com/cometbft/cometbft/blob/v0.38.22/blocksync/reactor.go is the wedge. NullRabbit-original measurement.
CVE-2026-49866: gossipsub oversized IHAVE/IWANT control-message arrays (huge messageID lists) → per-ID processing → CPU DoS
Oversized Control-Message Array CPU Burn
Oversized Hex String Parsing CPU Exhaustion
CVE-2019-11636 (Zcash 'Sapling Wood-Chipper'): Zcash 2.x raised the max transaction size from 100 KB to the full block size after Sapling, letting an attacker cheaply build block-filling shielded txs (fee 0.0001 ZEC/tx; ~0.0576 ZEC/day fills all ~576 daily blocks) and flood them onto the P2P network so no real transaction can be mined — a Slowloris-style asymmetric DoS on the whole chain. Fixed by reverting the max-tx-size cap to 100 KB (~10-40x cost). Modelled here as the P2P tx/inv flood wire signature; per-tx shielded-output count scaled down for capture.
quic-go QUIC path-validation memory exhaustion (CVE-2023-49295): flood of QUIC v1 short-header (1-RTT) packets each carrying PATH_CHALLENGE frame(s) (type 0x1a + 8B challenge data). Each PATH_CHALLENGE obliges the receiver to enqueue a PATH_RESPONSE (type 0x1b); the attacker keeps that queue from draining by collapsing the congestion window (selective ACK) and skewing the RTT estimate, so the queue of un-sendable responses grows without bound -> memory exhaustion. The 'distributed' posture additionally sources the flood from many CHANGING (spoofed) loopback addresses — each a new path that itself triggers path validation (the connection-migration angle of the same CVE). A loopback mock cannot complete a real TLS 1.3 handshake or negotiate real congestion state, so the load-bearing wire artefacts modelled are the PATH_CHALLENGE frame type, the flood density, and the changing-source-address path fan (not real QUIC keys / cwnd). public-cve-replication — replicated wire signature, not a NullRabbit measurement. Affected quic-go v0.40.0, <= v0.39.3, <= v0.38.1, <= v0.37.6; fixed v0.40.1, v0.39.4, v0.38.2, v0.37.7; severity Moderate; reported by marten-seemann (2024-01-10). Analysis: https://seemann.io/posts/2023-12-18-exploiting-quics-path-validation/. https://github.com/quic-go/quic-go/security/advisories/GHSA-ppxx-5m9h-6vxf
Path Challenge Response Memory Exhaustion
quiche QUIC PATH_CHALLENGE unbounded-queue flood (CVE-2023-6193): flood of QUIC 1-RTT short-header packets on one DCID arriving from CHANGING source paths (rotating loopback 4-tuples = QUIC connection migration), each carrying a PATH_CHALLENGE frame (type 0x1a) with fresh 8-byte challenge data. The recipient must echo each as a PATH_RESPONSE (type 0x1b) but, cwnd-restricted, drains slower than challenges arrive, so quiche's pending path-validation queue grows without bound. Real CVE is post-handshake 1-RTT frames; a loopback mock cannot complete a real TLS 1.3 handshake, so the queue-growth wire signature is modelled on the QUIC short-header PATH_CHALLENGE surface (frame type 0x1a + changing source paths on a fixed DCID + ever-fresh challenge data are the load-bearing artefacts). public-cve-replication — replicated wire signature, not a NullRabbit measurement. Affected quiche 0.15.0 through 0.19.0; fixed 0.19.1; CWE-400; CVSS 3.1 5.3 (Moderate). https://github.com/cloudflare/quiche/security/advisories/GHSA-w3vp-jw9m-f9pm
Path Migration Challenge Queue Exhaustion
Payload Window Overflow Memory Exhaustion
Cardano PeerSharing MsgShareRequest O(N log N) sort CPU amp: sortBy+hashWithSalt over the ~3000-peer known set per request (~170 us), no idle timeout (Codec.hs:160), no per-peer rate limit. One post-handshake connection flooding MsgShareRequest pins ~10-20% of a core; multi-attacker linear. NullRabbit measurement; chains/cardano/findings/H_CARDANO_4_PEERSHARING.
CVE-2023-40583: unchecked signed peer-record flood (peer-exchange) → go-libp2p peerstore OOM
Peer Record Signature Bypass Impersonation
Timejacking (SlowMist Blockchain Common Vulnerability List; Culubas 2011): N peers advertise a version.timestamp skewed ~+70min (inside the AddTimeData ±70min acceptance window) → each peer's derived time-offset drags the node's median network-adjusted time → block-time (nTime/MTP) validation clock drift → stale-tip / block-rejection isolation. SlowMist gap class; no CVE.
CVE-2024-32984 (GHSA-3999-5ffv-wp2r): rust-yamux (0.13.0 .. <0.13.2) buffers frames-to-send in an unbounded `pending_frames` VecDeque. A remote peer floods Ping frames (each enqueues a Pong reply) and/or opens streams while stalling its own TCP receive window (never sending WindowUpdate), so the victim's outbound frame queue cannot drain and grows without bound → remote memory exhaustion (fixed in 0.13.2, which bounds the queue).
Pre-Handshake Buffer Reservation Exhaustion
Bitcoin Core BIP-324 v2 transport pre-auth CPU burn: the 64-byte inbound ellswift key triggers secp256k1 ellswift ECDH + HKDF-SHA256 BEFORE any auth/rate-limit; only the soft 125-inbound cap gates, accept path single-threaded. Churn of 64-byte-key connections pins a core. Measured HIGH on Bitcoin Core (55x p50/256x p99 honest-peer latency at 4 IPs) + Qtum; default-on since Core 27.0. NullRabbit measurement; chains/bitcoin/findings/BTC_V0_BIP324_PREHANDSHAKE_CPU.
How CometBFT's SecretConnection handshake spends CPU before authenticating the peer
Qtum BIP-324 Pre-Authentication ECDH CPU Exhaustion
EL-2026-06 (EF public-disclosure): RLPx pre-auth packet flood → CPU/bandwidth exhaustion
CometBFT consensus DataChannel(0x21) ProposalMessage flood: valid-shape Proposal passes ValidateBasic but the RLock+queue path runs before deferred sig-verify — the N1.4 family HEAD (vote-flood + blocksync-flood are its siblings). NullRabbit-original consensus-reactor measurement.
Premature Disconnect Request Handling Crash
GHSA-p7mv-53f2-4cwj (ASA-2024-011): a Precommit with a non-nil BlockID + an attached vote extension is handled BEFORE the ValidatorIndex is verified → out-of-range ValidatorIndex → index-out-of-range panic on the ValidatorSet lookup (CometBFT >=0.38, fixed v0.38.15).
Premature Processing Index-Out-Of-Range Panic
CVE-2023-40591: post-Hello devp2p PING (0x02) flood → unbounded goroutines → OOM (geth 1.10.0-1.12.0)
Protocol Message Flood Unbounded Goroutine
QUIC Connection ID Retirement Infinite Loop
QUIC Connection Migration Duplicate-ID Crash
s2n-quic stream-limit exhaustion (GHSA-475v-pq2g-fp9g): pre-patch `RemoteInitiated::on_close_stream` directly bumped `max_streams_sync` with NO rate limiting, so every close of a remote-initiated stream immediately re-grants stream credit (and makes s2n-quic emit a MAX_STREAMS frame). A peer that rapidly opens-and-closes remote-initiated streams (STREAM open+FIN then RESET_STREAM) while signalling STREAMS_BLOCKED to pull the limit up drives uncontrolled stream-controller churn / limit-sync traffic — 'unnecessary resource utilization when peers open streams beyond advertised limits' (CWE-400). No workaround; fixed in s2n-quic v1.31.0 by adding an RTT-based TokenBucket in RemoteInitiated to throttle the limit increase. Severity Low. PUBLIC-CVE REPLICATION — wire signature only (loopback UDP mock, no s2n-quic server stood up).
QUIC Unauthenticated Close Frame Disruption
IC ingress-pool per-NodeId quota mis-key (IC_N1_INGRESS_POOL_QUOTA_MISKEY): every HTTP-arriving ingress message buckets under the carrier replica's own NodeId instead of the signing principal (call.rs:391), so a single shared per-NodeId quota gates ALL public HTTP ingress. Submitting 10001 small signed HTTP ingress POSTs trips exceeds_limit (measured 0.04s at production caps 10000 / 100 MB); the handler's RemoveFromUnvalidated then purges 100% of legit unvalidated HTTP ingress on that replica at the next on_state_change (~200ms). PUBLIC reach; ~50k signed-ingress/s keeps a replica wiped; ~40 MB total bandwidth pins a 40-replica subnet. NullRabbit measurement; chains/ic/findings/IC_N1_INGRESS_POOL_QUOTA_MISKEY.
IOTA_S1_EVENTFILTER_EXPONENTIAL: iotax_subscribeEvent depth-D balanced Or-tree filter → exponential CPU
GHSA-8wcc-m6j2-qxvm (ASA-2024-0012/0013): deeply-nested protobuf Any → TxDecoder/UnpackAny stack-overflow / exponential CPU+mem in CheckTx (pre-validation)
Recursive Message Deserialisation Stack Overflow
Solana repair-protocol orphan DoS (solana-labs/solana v1.1.16, PR #10290): a legacy no-nonce RepairProtocol::Orphan(ContactInfo, slot) request for a slot > UNLOCK_NONCE_SLOT makes the serving node's serve_repair.rs::run_orphan loop through ALL slot metas in the blockstore building responses, 'effectively DOSing repair'. A tiny unauthenticated UDP orphan request over the serve_repair port thus commits the target to blockstore-proportional CPU (small request -> disproportionate server CPU, compute_amp). Fixed by breaking the loop when repair_response_packet returns None. Public release-note security fix, no CVE -> source_class = public-cve-replication.
eth RPC request-flood (full-tx block fetch sustained at high rate)
Scope Permission Bypass Unauthorized Write
Signature Malleability Consensus Manipulation
CVE-2024-52922: cmpctblock announce then stall (never answer getblocktxn) → ~10min delayed propagation
discv4 FINDNODE->NEIGHBORS reflection/amplification (NethermindEth/nethermind#12211): discv4 is Ethereum's connectionless-UDP node-discovery protocol. A ~170 B FINDNODE (packet-type 0x03) makes the node answer with a NEIGHBORS packet (type 0x04) of up to 16 node records (~8-13x larger). Pre-fix the node honoured FINDNODE without a PING/PONG endpoint proof bound to the exact UDP IP:port, so an attacker SPOOFING the victim's source IP reflects+amplifies the large NEIGHBORS replies onto the victim (DRDoS), and a FINDNODE burst starves the discovery response budget. #12211 requires endpoint-proof bonding (proof from endpoint A no longer authorizes requests to endpoint B) + splits the discovery rate-limit budget 50/50 between outbound requests and protocol responses. Wire framing is faithful (hash[32]||sig[65]||type||rlp; hash=keccak256(sig||type|| data)); a VALID secp256k1 signature is NOT required for the capture — the wire SHAPE + flood is the signature — so the 65-byte sig is synthetic. PUBLIC-FIX REPLICATION — loopback UDP mock plays the node (replies NEIGHBORS); no real Nethermind/geth discovery service stood up.
Spoofed Endpoint-Proof Bypass Amplification
State Sync Proposer Priority Mismatch Chain Split
C04 (COSMOS_SUBSCRIBE_PERCONN_CAP): CometBFT rpc/core/events.go:27 caps NumClients>=MaxSubscriptionClients(100) but clientID=RemoteAddr(ip:PORT) → each TCP conn gets an independent per-client cap → subscription multiplication across many connections from one IP
CVE-2025-24371 (ASA-2025-001 / GHSA-22qq-3xwm-r5x4): a malicious CometBFT blocksync peer disrupts a node's ability to sync. In blocksync a peer reports its base/latest heights in a StatusResponse; the attacker advertises an inflated `latest` (the sync target) then advertises LOWER heights. The target is never recalculated downward, so the node tries to catch up to an unreachable height indefinitely → blocksync deadlock (restarted/new nodes cannot rejoin). Affected cometbft <= v0.38.16 and v1.0.0; fixed v0.38.17, v1.0.1. Wire signature: StatusResponse frames whose `latest` spikes high then steps DOWN, plus BlockRequests answered only by NoBlockResponse on the Blocksync channel 0x40.
CVE-2026-52737 (GHSA-gvjc-3w7c-92jx): a single unauthenticated Zcash P2P peer answers the syncing node's getblocks/FindBlocks with a two-hash inv, then serves a `block` whose coinbase height is above tip+VERIFICATION_PIPELINE_DROP_LIMIT. Zebra returns AboveLookaheadHeightLimit, which lacks the peer address, so it triggers a GLOBAL sync restart (~67s mainnet penalty, cancels all in-flight downloads) instead of banning the peer. Repeating the (inv -> above-lookahead block) cycle pins the node in a perpetual restart loop — sustained sync-degradation DoS from one unauth peer. Node does not crash. Affected zebrad<=4.4.1 / zebra-consensus<=6.0.0; fixed v4.5.0/7.0.0 (failures made peer-local + peer banned).
CVE-2024-52912: version nTime=INT64_MIN → abs64 overflow skews adjusted-network-time → netsplit
Transaction Malleability (SlowMist Blockchain Common Vulnerability List): a tx and a malleated sibling with a byte-different scriptSig (extra OP_NOP) → different txid, identical inputs/outputs/effect; relaying both lets the mutant confirm under a new txid, breaking original-txid tracking (classic pre-SegWit malleability). SlowMist gap class; no CVE.
Tx History Storage Flood Disk Exhaustion
CVE-2024-55563 (Bitcoin Core <= 27.2): transaction-relay jamming via an off-chain protocol attack ('Transaction-Relay Throughput Overflow Attacks against Off-Chain Protocols'; related to CVE-2024-52913). High-overflow variant: a flood of many small higher-feerate txs + their inv announcements overflows the fee-rate-sorted forward-transaction inventory (INVENTORY_BROADCAST_MAX / CompareInvMempoolOrder), so a lower-feerate pre-signed Lightning HTLC/commitment tx is never announced (jammed) before its timelock expires -> HTLC outcome changed.
Transaction Validation Logic Consensus Split
Black Valentine (SlowMist Blockchain Common Vulnerability List): geth --http with the personal namespace exposed + an unlocked/unlockable account → remote unauthenticated personal_unlockAccount then eth_sendTransaction flood drains the wallet. No CVE.
Unauthenticated Admin Interface Exposure
CVE-2020-5303 (Lavender): unlimited CometBFT P2P connection requests → OOM + activeIDs-map saturation
quic-go connection-ID memory exhaustion (CVE-2024-22189, GHSA-c33x-xqrf-c478): on an established QUIC connection the attacker floods NEW_CONNECTION_ID frames (type 0x18) with an escalating 'Retire Prior To' field. Each escalation forces the peer (RFC 9000 §19.15) to retire the connection IDs below it and to queue a RETIRE_CONNECTION_ID frame per retirement. The attacker prevents the peer from ever draining that queue by collapsing its congestion window (selective ACKing) and inflating its RTT estimate, so the RETIRE_CONNECTION_ID frames accumulate unbounded → peer runs out of memory (CWE-770, no per-connection cap). No workaround; fixed in quic-go v0.42.0. PUBLIC-CVE REPLICATION — wire signature only (loopback UDP mock, no quic-go server stood up).
Unbounded Filter Subscription Storage Exhaustion
Sybil (SlowMist Blockchain Common Vulnerability List): a flood of full RLPx+eth-handshake peers each with a DISTINCT node identity occupies the target's inbound peer slots and biases peer selection (eclipse precursor); accepted as full peers, unlike blank handshake floods or alien-chain pollution. SlowMist gap class; no CVE.
CVE-2026-35457 (GHSA-v5hw-cv9c-rpg7): libp2p-rendezvous server stores DISCOVER pagination cookies in an unbounded in-memory map (Registrations::cookies) with no size cap / eviction / expiry — a flood of unauthenticated /rendezvous/1.0.0 DISCOVER requests forces one fresh Cookie + HashSet entry per request → linear memory growth → remote memory exhaustion (fixed in 0.17.1).
Unbounded Registration Storage Exhaustion
PRYSM_ATTESTER_SLASHING_PUBKEY_BURN (S4): POST /eth/v1/beacon/pool/attester_slashings_v2 decodes one AttesterSlashingElectra whose attesting_indices vector is capped only at the structural MaxValidatorsPerCommittee*MaxCommitteesPerSlot = 131,072 (attestation.go:259; no body cap, no rate-limit) then runs a per-index pubkey-deser/subgroup-check loop before the pairing short-circuits → 3.06 s/req cold-cache measured. NullRabbit-original on prysm HEAD; no CVE.
Unbounded Request Body Memory Exhaustion
Cardano cardano-submit-api: unbounded request body → memory exhaustion
The node's JSON-RPC handler for batched account-lookup calls (e.g. getMultipleAccounts) imposes no response-size accounting or cost weighting relative to request size, only a flat cap on key count. An attacker submits a small request (~4.8KB) listing well-known large program accounts (Token/BPFLoader2/BPFLoaderUpgradeable), whose ELF/program data stubs are echoed in full, driving a single request to a ~17.8MB response (3,708x amplification) and sustained ~830MB/s egress under parallel workers. The fix-class is response-size-aware rate limiting/cost accounting on batched read RPCs (weighting by bytes returned, not just item count), not a request-count cap.
How a wide-range eth_getLogs query turns a few hundred bytes into an unbounded response on exposed go-ethereum RPC nodes
Unbounded Signature Verification CPU Exhaustion
CVE-2022-23492/CVE-2022-23486: libp2p stream/connection exhaustion (no backpressure) → OOM
CoreDNS DoQ stream slowloris (CVE-2025-47950 / GHSA-cvx7-x8pj-x2gw): CoreDNS' DNS-over-QUIC server created a new goroutine for every incoming QUIC stream with NO cap on concurrent streams/goroutines (1:1 stream->goroutine). The DoQ framing (RFC 9250: 2-octet big-endian length prefix per DNS message) reads that prefix and the body with blocking io.ReadFull() calls that have NO per-stream read deadline. A remote, unauthenticated attacker opens many QUIC streams (e.g. 60 conns x 256 streams = 15,360) and sends only 1 byte on each — the first byte of the length prefix — then stalls; each io.ReadFull blocks forever waiting for the second byte, pinning a worker goroutine, and once workers are exhausted every further stream still spawns a goroutine that blocks on a worker token, so goroutine/RSS grow without bound -> OOM-kill/crash (a QUIC-native slowloris), especially in memory-constrained containers. CVSS 7.5 HIGH (AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H). Affects `quic://`-enabled Corefiles; no workaround; fixed v1.12.2 (max_streams default 256 + bounded worker_pool_size default 1024). Fix was incomplete — regression CVE-2026-32934 / GHSA-2wpx-qpw2-g5h5, fixed v1.14.3. PUBLIC-CVE REPLICATION — wire signature only (loopback UDP mock, no CoreDNS DoQ server stood up).
NullRabbit source-traced IOTA GraphQL unbounded-subscription flood (operator-gated).
Unbounded Task Spawn Resource Exhaustion
CVE-2023-42805 (RUSTSEC-2023-0063): quinn-proto < 0.9.5/0.10.5 panics on a QUIC frame with an UNKNOWN frame type (RFC 9000 §12.4 requires FRAME_ENCODING_ERROR, not a crash). A single packet carrying one undefined-type frame crashes the endpoint (availability DoS). Fixed by principled invalid-frame error handling (quinn PR #1667). Modelled as the unknown-frame-type wire signature. https://rustsec.org/advisories/RUSTSEC-2023-0063.html
E28/SOL_P07: getProgramAccounts filter-miss CPU scan (agave rpc.rs:2235-2251)
Unindexed Account Scan CPU Amplification
CVE-2023-33297 (drain): un-rate-limited getheaders flood → >100MB/s upload (Bitcoin/Litecoin/Dogecoin)
Unsafe Deserialization Memory Corruption
QUIC SCID hash-collision DoS (CVE-2025-47200): a flood of QUIC v1 Initial packets whose 8-byte Source Connection IDs are crafted to COLLIDE in the server's connection-ID hash table. The server keys active connections on the peer SCID; a weak non-seeded hash (NCC names FNV, xxHash, and `hash = hash*31 + char`) lets the attacker hold a constant 5-byte SCID prefix (5c1dc011de) and vary a 3-byte counter suffix, keeping only suffixes whose full-SCID hash lands in one target bucket — so every DISTINCT SCID collides. Worst-case O(n) bucket walks (amortised O(n^2)) burn server CPU: NCC measured ~300x slowdown from 10k parallel colliding connections. Only SipHash (keyed) mitigates. PUBLIC-CVE replication of the NCC Group / Fox-IT advisory; new corpus wire family = algorithmic-complexity / hash-DoS.
CVE-2024-52921: unrequested merkle-mismatched block erases other peers' download state → hinders propagation
CVE-2026-45783 / GHSA-32mq-hpph-xfvr: the libp2p Kademlia DHT (@libp2p/kad-dht (npm, js-libp2p), affected < 16.2.6) accepts and persists PUT_VALUE records with no effective validation, count, or byte budget. Two combined defects: (1) `verifyRecord` silently returns early for keys with fewer than 3 slash-delimited parts, so a crafted key bypasses all content validation and the record is written to the datastore anyway; (2) the RPC message loop resets its inactivity timeout after each message and imposes NO per-stream message-count limit and NO per-peer byte budget. Combined: an unauthenticated peer opens one /ipfs/kad/1.0.0 stream and floods distinct crafted PUT_VALUE records → the victim's datastore grows without bound until the host disk is exhausted and the DHT server node becomes unavailable. Server-mode DHT nodes are the default for publicly-routable addresses (IPFS/bootstrap nodes). No auth required. Fixed in 16.2.6 (rejects unrecognized keys instead of silently accepting them).
Unvalidated DHT Record Storage Exhaustion
Agave snapshot AppendVec StoredMeta.data_len > MAX_PERMITTED_DATA_LENGTH (10 MiB) survives new_for_startup (sanitize skipped) -> index-gen scan_accounts QuotaExceeded -> .expect("must scan accounts storage") panic; pre-hash-gate bootstrap crash. Out-of-scope per Anza SECURITY.md (maliciously-crafted-snapshots / bootstrap-config-mitigable) -> publishable. source_class=original.
Crashing an Agave validator during snapshot bootstrap with one oversized account length
CVE-2024-52916: difficulty-1 headers with parent=genesis → mapBlockIndex unbounded growth → memory DoS
CVE-2018-17145 (INVDoS): random-hash INV flood → unbounded tx-tracking memory
Unvalidated Inventory Tracking Memory Exhaustion
CVE-2016-10724: pre-0.13.0 alert messages stored in an unbounded map → memory exhaustion
Vote Signature Late Verification Resource Exhaustion
XML Attribute Parsing Quadratic CPU Exhaustion
XML Namespace Declaration Memory Exhaustion
monero PR #9052: with ZMQ-PUB enabled the ZMQ-RPC server uses zmq_poll; an INVALID non-ZMQ message (e.g. a browser HTTP request to the ZMQ-RPC TCP port) bypasses the poll filter, reaches zmq_read which returns EAGAIN, and the unhandled spurious wakeup PERMANENTLY crashes ZMQ-RPC until restart (remote availability DoS). Fixed by handling EAGAIN. Modelled as the HTTP-to-ZMQ-port wire signature. https://github.com/monero-project/monero/pull/9052
dnsdist's DoQ/DoH3 receiver allocates per-error bookkeeping state whenever it emits a self-generated FORMERR/REFUSED/SERVFAIL/NOTIMP response, and attaches that state to the QUIC connection object rather than the completed stream/query, freeing it only on full connection teardown. An attacker opens a single DoQ/DoH3 connection and streams a large run of complete, well-formed queries engineered to each trigger a local error response, causing the per-error allocations to accumulate unboundedly for as long as the connection (or its parallel siblings) stays open. The fix-class is scoping/freeing per-error bookkeeping to the query/stream lifetime instead of the connection lifetime, bounding memory growth regardless of connection duration.
Envoy's HTTP/2 HPACK decoder bounds header-block size on ENCODED bytes only, and cookie header bytes bypass the max_request_headers_kb decoded-size accounting entirely. An attacker plants one large cookie value once in the HPACK dynamic table via a literal-with-incremental-indexing field, then re-references that single entry many times per request using 1-byte indexed-header-field octets, so the wire stays tiny while Envoy materializes the full cookie value on every reference. The fix-class is bounding/accounting the DECODED header size (including cookie bytes) rather than just the encoded HPACK block, closing the asymmetric-allocation gap; without it, a few connections/streams balloon decoded-header memory past the process limit and get OOM-killed within seconds.
The HTTP/2 decoder's header-list-size guard is size-based (maxHeaderListSize - frameSize < currentSize) and never trips when each CONTINUATION frame carries zero bytes, so no count limit exists on CONTINUATION frames following an unterminated HEADERS block (END_HEADERS=0). An attacker opens a header block and streams an unbounded sequence of zero-length CONTINUATION frames on one connection, each costing only a 9-byte frame header to send. The decoder keeps parsing every frame, monopolizing a CPU thread and producing a compute-exhaustion DoS at negligible attacker bandwidth.
The HTTP/2 priority parser (RFC 9218 urgency field) throws an unhandled IllegalArgumentException when given an out-of-range value (e.g. u=99), and the request-handling code path lacks a catch/cleanup for this failure, leaving the half-processed request's state permanently retained. An attacker floods the server with malformed PRIORITY_UPDATE frames or priority headers, each triggering the same uncaught-exception path, causing unbounded cumulative memory retention across requests. Effect: gradual heap growth culminating in OutOfMemoryError / DoS. The fix-class is 'catch parser exceptions and ensure per-request cleanup/dispatch on all error paths', distinguishing it from stream-count or flow-control exhaustion techniques.
The QPACK decoder returns QUIC stream- and connection-level flow-control credit for HEADERS bytes belonging to field sections that reference dynamic-table entries not yet inserted (Required Insert Count > inserted count), even though those bytes remain resident in the decoder's blocked-section heap buffer. An attacker sends such blocked field sections and never supplies the corresponding encoder-stream inserts, so the sections never decode or free, while continuing to send more HEADERS traffic using the wrongly-returned flow-control credit. This decouples flow-control accounting from actual buffer occupancy, letting the attacker drive unbounded heap growth in the decoder and exhaust memory/DoS the HTTP/3 stack.
The node-side defect is an insecure default: the HTTP/3 codec's maxHeaderListSize defaults to the near-unbounded RFC 9114 ceiling ((1<<62)-1) whenever a peer omits SETTINGS_MAX_FIELD_SECTION_SIZE, instead of inheriting the safe bounded default already enforced for HTTP/1.1 and HTTP/2. An attacker simply never sends that setting, then transmits a HEADERS/QPACK block containing an enormous COUNT of distinct literal header fields; the codec keeps decoding and buffering each field with no size ceiling. The fix-class is enforcing a safe bounded default (and/or hard cap independent of peer-advertised settings) for field-section size in the HTTP/3 codec, which measurably manifests as unbounded heap growth culminating in OutOfMemoryError/process death.
The BLAKE2F precompile (0x09) exposes an attacker-controlled 'rounds' field that is charged at a flat 1-gas-per-round rate but executes synchronously on the node's RPC-serving thread; because gas cost scales linearly while wall-clock compute per round is effectively free to request, a small eth_call payload (~585 bytes) can force tens of millions of compression rounds. This yields a large asymmetry between request size/cost and CPU time consumed (~405ms vs ~1ms baseline), letting a single cheap call monopolize a worker thread and degrade node responsiveness. The fix-class is bounding/metering precompile-invoked loop primitives (rounds/iteration caps, tighter gas-to-wall-time calibration, or synchronous-call time budgets) at the eth_call/precompile-dispatch layer.
The node's qlog logging path assumes the CONNECTION_CLOSE/APPLICATION_CLOSE reason-phrase field is valid UTF-8 and decodes it directly into a Rust `str` for logging, even though RFC 9000 §19.19 defines the reason phrase as opaque bytes with no UTF-8 requirement. A remote peer sends a single CLOSE frame (0x1c/0x1d) whose reason-phrase bytes are deliberately invalid UTF-8 (e.g. stray continuation bytes), triggering a decode/conversion panic in the qlog writer and crashing the victim process — a one-packet availability DoS. The fix-class is defensive/lossy decoding (or byte-safe handling) of all peer-supplied opaque protocol fields before they are passed to logging, serialization, or string-typed APIs.
The node's connection-ID retirement handler does not terminate/converge when RETIRE_CONNECTION_ID and NEW_CONNECTION_ID sequence numbers are exchanged across multiple migrated paths in a circular pattern (retiring the CID in use on path A from path B and vice versa), violating the RFC 9000 §19.16 invariant that a packet must not retire the CID it was sent on. An attacker who completes the handshake and drives path migration across ≥2 paths while crafting this circular retirement sequence triggers an unbounded loop in the retirement logic (CWE-835), pinning the victim at 100% CPU — a post-handshake remote compute-exhaustion DoS. Fix-class is bounding/validating cross-path CID retirement transitions so the state machine always reaches a valid exit, distinct from fixes that bound the retired-CID store size for single-path floods.
The edge's rate limiter counts HTTP/2 cleartext (h2c) connections at layer 4 (per-IP connection count via limit_conn), while the backend (geth :8545) transparently terminates h2c and honors all multiplexed streams within it as independent requests. An attacker who prior-knowledge-upgrades a single TCP connection to h2c opens many concurrent streams (measured 20/20) inside that one connection, each carrying a full RPC call (e.g. eth_getLogs), so the edge sees '1 connection' while the backend processes N requests, yielding request/data-volume amplification (~43.9MB) with the per-IP connection cap never triggering. The defect class is a mismatch between the connection-granularity enforcement point and the stream-granularity request semantics of the multiplexed protocol; the fix-class is enforcing rate/connection limits at the stream (request) level for any multiplexed transport, or disabling/gating h2c cleartext upgrade at the edge so multiplexing cannot cross the limiter boundary.
One prior-knowledge h2c connection multiplexes N eth_getLogs past an L4 per-connection cap on go-ethereum's JSON-RPC port
The bridge signing server exposes its request-handling routes over plain HTTP with no authentication, no per-IP rate limit, and no concurrency/timeout cap — the only middleware layer checks body size, not request rate. An attacker sends cheap unauthenticated GETs to the signing endpoint, each of which the handler expands into backend RPC round-trips (fetch+verify) before signing, so request volume translates directly into backend work with no admission control to shed excess load. This lets a modest unauthenticated flood exhaust the signer's handling capacity, denying enough validators from completing signature assembly to halt the quorum (availability/censorship, not forgery).
Unauthenticated Crypto Signing CPU Exhaustion
The AutoNAT v2 server never initialises its per-peer rate-limiter map before use; any well-formed inbound DialRequest on the /libp2p/autonat/2/dial-request stream reaches serveDialRequest -> rateLimiter.CompleteRequest, which performs a write ('assignment to entry in nil map') on that nil map. The fix-class is server-side state initialisation (allocate/guard the map before first write) rather than any input-validation or protocol change, so the defect is a missing-initialisation bug triggered by any valid protocol handshake, causing a remote unauthenticated panic/crash (availability DoS).
The server's packet-coalescing space-accounting logic performs an unsigned subtraction of remaining datagram space when building its own coalesced Initial response, without checking that the incoming fragmented handshake (split across two CRYPTO frames in two coalesced Initial packets) hasn't already consumed more space than accounted for. An attacker sends a single UDP datagram with two coalesced QUIC Initial packets whose CRYPTO frames reconstruct an oversized (~1222B) ClientHello, triggering an 'attempt to subtract with overflow' at the coalescing arithmetic and crashing the server process pre-handshake. The fix-class is bounds-checked/saturating space accounting in the response-coalescing path, making this the same technique as any other unsigned-underflow-panic in QUIC packet-space bookkeeping triggered by oversized/fragmented handshake input.
Unsigned Integer Underflow Accounting Panic
The node's proposal-ingest path bounds-checks an attacker-supplied `signer` slot index against the validator-set size using a strict `>` comparison instead of `>=`, so the boundary value `signer == num_validators` passes the check. That value is then used to index the validator array via `get_validator_by_slot_band`, causing an out-of-bounds access, and this happens before any signature verification, so an unauthenticated peer can gossip a single crafted, unsigned proposal to crash every receiving validator. Fix-class: correct the off-by-one bound check (or otherwise validate/clamp the index) prior to array indexing, closing the pre-auth OOB panic (CWE-125/193).
Boundary-Check Off-By-One Index OOB Panic
handle_dht_get only creates the DhtResults accumulator when the FIRST returned Kademlia record verifies successfully; it never falls back to a later valid record if that first responder's record fails verification. A malicious peer wins the race by answering the get first with a well-formed but unverifiable record (e.g. correct-length but all-zero signature), causing the accumulator to never be initialized. Every subsequent honest, valid record is then compared against the missing/poisoned state and discarded as inconsistent, denying the querying node the real value and blocking peer/validator discovery and routing (improper handling of an unusual/exceptional first-response condition, CWE-754).
Tx::verify_signatures counts/indexes the public keys in a Section::Authorization using a u8-width counter; a single unauthenticated transaction whose Authorization section carries 256+ Ed25519 public keys (with matching valid signatures) overflows that u8 during mempool CheckTx. The overflow triggers a panic, crashing the validating node from one crafted broadcast_tx_sync submission. Fix-class is bounding/validating the authorization key-count (or widening the counter) before/during signature verification, i.e. an integer-overflow-in-untrusted-length-field defect (CWE-190) in mempool tx validation.
wasmd message types (MsgStoreCode, MsgStoreAndInstantiateContract, MsgUpdateInstantiateConfig, MsgAddCodeUploadParamsAddresses, etc.) carry an unbounded AccessConfig.Addresses/msg.Addresses list that ValidateBasic() de-duplicates via a map, and this validation runs during ABCI CheckTx before antehandler signature verification. An attacker submits a single unsigned tx via broadcast_tx_sync packing tens of thousands of distinct addresses (bounded only by tx-size gas cost and CometBFT max_bytes), causing large memory allocation and map-operation slowdown in the mempool of every node that receives it. The fix class is bounding/validating list length (or moving the check post-auth) in ValidateBasic before the map de-dup step.
Unbounded Address List Validation CPU Exhaustion
ASA-2024-003 / GHSA-4j93-fm92-rp4m (cosmos-sdk cosmos-sdk <= v0.50.3 / <= v0.47.8): x/auth/vesting MsgCreateVestingAccount / MsgCreatePermanentLockedAccount did not reject a blocked `to_address` (a module account on the bank blocklist), so one permissionless signed tx could create a vesting account at an uninitialised blocked module address; a later GetModuleAccount on it panics -> chain halt (CWE-20). Confirmed live: the signed tx reaches DeliverTx on patched gaiad v21 and is rejected with '<addr> is not allowed to receive funds: unauthorized' (the fix's guard); on a vulnerable node it halts the chain. Fixed v0.50.4 / v0.47.9. https://github.com/advisories/GHSA-4j93-fm92-rp4m
The node's transaction sighash routine fails to reject SIGHASH_SINGLE inputs whose index is >= the number of outputs; instead of throwing (the spec-mandated behavior), it silently substitutes an empty output set when computing the signature digest. An attacker crafts a transparent transaction with more inputs than outputs and signs the offending input with SIGHASH_SINGLE at an out-of-range index against this empty-set digest, producing a signature the defective node validates and accepts into its mempool/block template while spec-compliant nodes reject it. This divergence yields a direct block-validity consensus split between vulnerable and correct implementations.
SIGHASH_SINGLE Missing-Output Validation Gap
The node's transaction-verification layer fails to enforce the rule that a transparent-input signature's trailing hash-type byte must be one of the known canonical values (ALL/NONE/SINGLE and their ANYONECANPAY variants); this validation, previously enforced in an older verifier, was dropped during a parsing/verification refactor. An attacker submits a validly-signed transaction whose hash-type byte is an unrecognized value, which the defective node silently masks to a canonical type when computing the sighash digest instead of rejecting it outright. This causes the vulnerable node to accept and relay/mine a transaction that reference implementations reject, producing a deterministic block/mempool-validity consensus split between patched and unpatched nodes.
conflux-rust#3497 (conflux-rust light protocol): a single unauthenticated StorageRoots (clp msg_id 0x1b) whose roots[0].root.delta = RLP list [3] makes MptValue<H256>::decode hit `n => panic!` during RLP decode, before request-matching. Victim = a LIGHT node (its clp client handler decodes StorageRoots). Verified live vs vulnerable v3.0.3 (f44f1cb, node_type=light): after the clp handshake (StatusPingV2/StatusPongV2), one 0x1b panics thread 'Socket IO Worker' at primitives/src/storage.rs:144; ~2 msgs freeze P2P. Fixed by returning a DecoderError. https://github.com/Conflux-Chain/conflux-rust/pull/3497
Snapshot Manifest Boundary Validation Crash