CVE-2026-22868

Geth's Crypto-Kryptonite: DoS via KZG & ECIES Exhaustion

Amit Schendel
Amit Schendel
Senior Security Researcher

Jan 13, 2026·8 min read

Executive Summary (TL;DR)

Geth nodes < 1.16.8 are vulnerable to CPU exhaustion. Attackers can spam invalid 'Blob' transactions or malformed P2P handshake packets. The node politely verifies every single piece of garbage data instead of disconnecting the peer, leading to 100% CPU usage and effective denial of service. Update to v1.16.8 immediately.

A high-severity Denial of Service (DoS) vulnerability in Go-ethereum (Geth) allows malicious peers to crash or stall nodes via resource exhaustion. The issue stems from two distinct flaws: failure to fail-fast on invalid KZG proofs (introduced in EIP-4844) and an insufficient length check in ECIES encryption handshakes, causing the CPU to waste cycles on computationally expensive cryptographic verifications for invalid data.

The Hook: The Price of Politeness

In the world of blockchain, paranoia is a virtue. You assume everyone is lying to you until they prove otherwise mathematically. But there is a hidden cost to this paranoia: the verification itself. Every time a peer sends you a transaction, a block, or a handshake, your CPU has to burn electricity to check signatures and proofs. If the check is cheap, no problem. If the check is expensive—like, say, the heavy elliptic curve pairings used in EIP-4844—you have a potential loaded gun pointing at your scheduler.

CVE-2026-22868 is a classic case of "Kill them with kindness," or in this case, kill them with computation. It affects Go-ethereum (Geth), the execution client that powers the vast majority of the Ethereum network. The vulnerability essentially allows a malicious peer to force your node to perform heavy lifting for absolutely no reason.

It’s like a prank caller ringing a hotline that is legally required to listen to the entire complaint before hanging up. The attacker sends garbage, and Geth, being the polite protocol citizen it was, sat there and crunched the numbers on every single byte of that garbage, ignoring the fact that the first byte was clearly wrong. By the time the node realized it was being played, it was already too late—the CPU cycles were gone, and legitimate blocks were being dropped on the floor.

The Flaw: A Tale of Two Vectors

This vulnerability is actually a "buy one, get one free" special involving two distinct parts of the networking stack: the modern EIP-4844 Blob verification and the legacy ECIES encryption handshake.

Vector A: The KZG Exhaustion (EIP-4844)

When Ethereum implemented Proto-Danksharding (EIP-4844), it introduced "blobs"—large chunks of data attached to transactions. To prove that the data exists without downloading all of it, we use KZG (Kate-Zaverucha-Goldreich) proofs. Verifying a KZG proof is not free; it involves complex polynomial commitments and elliptic curve pairings.

The flaw in Geth's TxFetcher was a logic error in batch processing. When a peer sent a batch of blob transactions, the node would iterate through them to verify their proofs. Logic dictates that if the first proof is invalid (a cryptographic violation), the peer is malicious, and you should disconnect immediately. Geth, however, logged the error but continued processing the rest of the batch. It burned CPU verifying 100 invalid proofs when it should have stopped at the first one.

Vector B: The ECIES Handshake

Before two nodes even talk about transactions, they perform a handshake using ECIES (Elliptic Curve Integrated Encryption Scheme). Decryption is a multi-step process: verify the MAC, check lengths, and then perform ECDH (Elliptic Curve Diffie-Hellman) to derive the shared secret.

ECDH is the most expensive operation here. The vulnerability was a sloppy length check. The code checked if the packet was long enough to contain the overhead headers (rLen + hLen + 1), but it didn't check if it was long enough to actually contain a full block of ciphertext for the symmetric cipher (AES). This allowed an attacker to send a "short" packet that passed the initial check, forcing the node to run the expensive ECDH calculation, only to fail moments later when the symmetric decryption realized the data was missing.

The Code: Analyzing the Fix

Let's look at the "before" and "after" to understand exactly how the Geth team patched this. This is a great example of defensive programming.

Fixing the KZG Loop (Vector A)

In eth/fetcher/tx_fetcher.go, the original code looped through transactions and handled errors somewhat passively. The patch introduces a "hard stop" mechanism.

[!NOTE] The key change is treating ErrKZGVerificationError as a fatal protocol violation immediately.

// eth/fetcher/tx_fetcher.go
 
// BEFORE: Loop continues after error (simplified logic)
for _, tx := range transactions {
    if err := validate(tx); err != nil {
        log.Warn("Invalid tx", "err", err)
        // The loop continues to the next transaction!
    }
}
 
// AFTER: Break the loop immediately
case errors.Is(err, txpool.ErrKZGVerificationError):
    violation = err
    // ... logging ...
 
if violation != nil {
    f.dropPeer(delivery.origin) // Goodbye, malicious peer
    break // STOP processing this batch
}

By adding that break, the attacker can no longer force the node to verify the remaining 999 garbage blobs in the payload. The connection is severed instantly.

Fixing the ECIES Check (Vector B)

In crypto/ecies/ecies.go, the fix is a subtle math adjustment. It ensures we don't proceed to ECDH unless we have at least one full block of ciphertext.

// crypto/ecies/ecies.go
 
// BEFORE: Only checked for 1 byte of body
if len(c) < (rLen + hLen + 1) {
    return nil, ErrInvalidMessage
}
 
// AFTER: Checks for a full block size (usually 16 bytes for AES)
if len(c) < (rLen + hLen + params.BlockSize) {
    return nil, ErrInvalidMessage
}

This small change (checking params.BlockSize instead of 1) effectively filters out the malformed short packets before the heavy math kicks in.

The Exploit: Cooking the Grenade

Exploiting this does not require high privileges; you just need to be a peer in the swarm. The attack strategy is straightforward: resource exhaustion via asymmetry. We want to spend very little CPU to force the victim to spend a lot.

Scenario 1: The Blob Bomb

  1. Preparation: We modify a Geth client to bypass its own outgoing validation checks. We create a script that generates legitimate-looking NewPooledTransactionHashes messages.
  2. Payload: We construct a transaction batch containing 4096 blob transactions. The data inside the blobs is random noise (cheap to generate). The KZG proofs attached are also random noise.
  3. Delivery: We connect to the target node. We complete the handshake (legitimately). Then, we stream our "Blob Bomb".
  4. Effect: The victim receives the batch. It validates Blob #1. The KZG verification math runs (expensive). It fails. It logs a warning. Then it moves to Blob #2. It runs the math again. It fails. It logs. It repeats this thousands of times. While this is happening, the networking thread is locked up, and CPU usage spikes.

Scenario 2: The ECIES Short-Circuit

  1. Preparation: We write a Python script using scapy or raw sockets.
  2. Payload: We craft a TCP packet targeting port 30303. The payload mimics the ECIES header structure but sets the total length to be rLen + hLen + 2 (just enough to pass the old check, but too short for AES).
  3. Flood: We flood the target with these handshake initiation packets from spoofed IPs (if UDP/Discovery) or just rapidly open connections (TCP).
  4. Effect: The victim accepts the connection, parses the header, and immediately jumps into GenerateShared(priv, pub, ...)—the ECDH calculation. This eats CPU cycles before the function returns an error regarding the missing cipher block.

The Impact: Why You Should Care

While this isn't a Remote Code Execution (RCE) vulnerability that will leak your private keys, it is a significant Availability risk. In a decentralized network, availability is security.

If an attacker can crash or stall a significant percentage of Geth nodes:

  1. Network Partition: The network could struggle to reach consensus if enough validators are taken offline.
  2. Validator Slashing: If you are running a validator and your node is CPU-bound verifying garbage, you might miss your attestation window. In Ethereum, missing your duties leads to penalties (leaking) or missed rewards.
  3. Transaction Censorship: A sustained DoS attack could prevent legitimate transactions from propagating to the mempool.

CVSS 7.1 is "High" for a reason. It's low complexity, requires no auth (other than P2P access), and has a high impact on availability. For node operators running on constrained hardware (like home stakers on NUCs), this could brick their setup until the attack stops.

Mitigation: Patching and Defense

The remediation is simple: Update Geth.

Immediate Actions:

  • Upgrade: Pull the latest docker image ethereum/client-go:v1.16.8 or build from source using the latest stable tag.
  • Verification: Ensure your version string output by geth version shows 1.16.8 or higher.

Defense in Depth:

  • Sentries: Use sentry nodes (proxies) in front of your validators. If an attacker DoSes the sentry, your validator (where the keys live) remains safe, though disconnected from the network.
  • Resource Limits: Ensure your system has ulimits configured correctly so a crashing process restarts automatically (systemd), though this doesn't stop the attack, it just recovers from it.
  • Firewall: While you can't block P2P ports generally, if you have a static set of peers (e.g., a corporate consortium), whitelist only those IPs. For public Ethereum, this is not feasible.

This patch is a "hard fork" in logic, forcing the node to be intolerant of cryptographic errors. It brings the code in line with the "fail-fast" principle which is crucial for high-performance distributed systems.

Fix Analysis (1)

Technical Appendix

CVSS Score
7.1/ 10
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
EPSS Probability
0.12%
Top 100% most exploited
6,000
via Ethernodes.org

Affected Systems

Go-ethereum (Geth) Execution ClientEthereum Mainnet NodesLayer 2 nodes based on Geth (Optimism, Base, etc.)

Affected Versions Detail

Product
Affected Versions
Fixed Version
go-ethereum
ethereum
< 1.16.81.16.8
AttributeDetail
CWE IDCWE-20
Attack VectorNetwork (P2P)
CVSS v4.07.1 (High)
ComponentTxFetcher & ECIES
ImpactDenial of Service (CPU Exhaustion)
Exploit StatusPoC Available
CWE-20
Improper Input Validation

The product receives input or data, but does not validate or incorrectly validates that the input has the properties that are required to process the data safely and correctly.

Vulnerability Timeline

Fix committed to master branch
2026-01-09
GHSA Advisory Published
2026-01-13
Geth v1.16.8 Released
2026-01-13

Subscribe to updates

Get the latest CVE analysis reports delivered to your inbox.