CVE-2026-22862

Geth Crash Course: CVE-2026-22862

Alon Barad
Alon Barad
Software Engineer

Jan 13, 2026·6 min read

Executive Summary (TL;DR)

If you run Geth < 1.16.8, a malicious peer can kill your node instantly with a tiny, malformed encrypted packet. Alternatively, they can flood you with bad math (invalid KZG proofs) to melt your CPU. Update now or enjoy the silence.

A critical Denial of Service vulnerability in go-ethereum (Geth) allows connected peers to crash the node via malformed ECIES messages or exhaust CPU resources through invalid KZG proofs.

The Hook: The Backbone Breaker

Ethereum isn't just a currency; it's a world computer. And like any computer, it needs an operating system. For the vast majority of the network, that OS is go-ethereum (Geth). It processes transactions, maintains the state, and talks to other nodes. When Geth sneezes, the network catches a cold. When Geth crashes? We have a problem.

CVE-2026-22862 is a classic tale of "trusting input a little too much." It’s a two-headed monster offering attackers a choice: do you want to kill the node instantly with a panic (The Fast Death), or do you want to torture it slowly by burning its CPU cycles until it becomes a zombie (The Slow Death)?

This vulnerability exploits the P2P layer—the very mechanism nodes use to gossip about transactions. By joining the network and whispering a few malformed bytes (or some bad math), an attacker can take down validators, infra providers, and unsuspecting home stakers without breaking a sweat.

The Flaw: A Tale of Two Vectors

This vulnerability is actually a buy-one-get-one-free deal involving two distinct failures in input handling.

Vector A: The ECIES Panic (Fast Death) ECIES (Elliptic Curve Integrated Encryption Scheme) is used to secure communications. It combines asymmetric crypto (to share a secret) with symmetric crypto (AES) to encrypt the actual data. The flaw here is embarrassingly simple: the code checked if the message was long enough to contain the public key and the MAC, but it forgot that AES operates on blocks.

If you tell the AES decryption routine, "Here is 1 byte of ciphertext," and the cipher expects a 16-byte block, the underlying Go runtime screams and panics. Since Geth didn't recover from this panic, the entire process dies. It's like checking if a passenger has a ticket but forgetting to check if the plane has seats before boarding them.

Vector B: The KZG Exhaustion (Slow Death) With EIP-4844 (Proto-Danksharding), Ethereum introduced "blobs" and KZG commitments. Verifying a KZG proof is mathematically expensive (involving elliptic curve pairings). The flaw? Geth would happily verify invalid proofs sent by a peer, realize they were bad, and then... keep talking to that peer.

An attacker could stream thousands of transactions with garbage proofs. Geth would dutifully crunch the numbers, burn 100% CPU to realize "hey, this is math-garbage," and then accept the next one. It’s an asymmetric resource attack: cheap for the attacker to generate, expensive for the victim to verify.

The Code: One Byte Too Short

Let's look at the smoking gun in crypto/ecies/ecies.go. This is where the panic happens.

The Vulnerable Code:

// rLen is public key length, hLen is MAC length
// The check ensures we have at least 1 byte of body... right?
if len(c) < (rLen + hLen + 1) {
    return nil, ErrInvalidMessage
}

Technically, + 1 ensures there is some body. But the standard AES block size is 16 bytes. If len(c) leaves only 1 byte for the cipher, the subsequent call to the block mode decrypter triggers a bounds check failure in the Go runtime.

The Fix (Commit abeb78c647e354ed922726a1d719ac7bc64a07e2):

// Enforce full block size
if len(c) < (rLen + hLen + params.BlockSize) {
    return nil, ErrInvalidMessage
}

Meanwhile, in eth/fetcher/tx_fetcher.go, the fix for the CPU exhaustion was simply to stop being so polite. If a peer sends a bad KZG proof, it's not a mistake—it's an attack.

case errors.Is(err, txpool.ErrKZGVerificationError):
    // Don't just ignore it. Flag it.
    violation = err
...
if violation != nil {
    f.dropPeer(delivery.origin) // BEGONE!
    break
}

Prior to this, the code would just log the error and continue the loop, allowing the peer to send another bad proof immediately.

The Exploit: Crashing Nodes for Fun and Profit

Exploiting this doesn't require a supercomputer. It requires a modified Geth client or a simple Python script speaking the RLPx protocol.

The "Kill Switch" (ECIES)

  1. Handshake: Perform the standard cryptographic handshake to establish a session with the victim node (port 30303).
  2. Craft the Payload: Create an ECIES message structure.
    • Public Key: Valid curve point.
    • MAC: Valid HMAC.
    • Ciphertext: 1 byte of junk (0x00).
  3. Fire: Send the packet.
  4. Impact: The remote Geth process hits panic: runtime error: index out of range and terminates immediately. Systemd might restart it, but if you keep sending the packet, the node stays down forever.

The "Cpu Burner" (KZG)

  1. Connect: Establish a valid P2P connection.
  2. Spam: Generate validly formatted BlobTx transactions but fill the KZGProof field with random bytes.
  3. Loop: Send these in NewPooledTransactionHashes (0x01) or Transactions (0x02) messages.
  4. Impact: The victim's CPU spikes. Other peers get ignored. Block validation lags. The node becomes useless but stays "online," which can be even worse for monitoring systems than a hard crash.

The Impact: Why You Should Care

If you are running a generic node for querying data, this is an annoyance. You restart, you ban the IP, you move on.

However, if you are a validator, this is dangerous. A targeted attack could knock your validator offline during its attestation duties, leading to penalties (slashing/leaking). If a significant percentage of the network is vulnerable (and Geth market share is usually >50%), a coordinated attack could threaten network finality.

Furthermore, the CPU exhaustion vector is insidious. Cloud providers charge by the CPU credit. An attacker could force your node to burn through expensive compute resources, effectively launching a "Financial Denial of Service" against your AWS bill.

The Fix: Update or Else

There is no fancy config flag to fix a runtime panic in the crypto library. You have to update the binary.

Immediate Action: Upgrade to Geth v1.16.8 or later. This release includes the patch for both the ECIES panic and the KZG peer-dropping logic.

Defense in Depth:

  1. Sentry Nodes: Never expose your validator directly to the public internet. Use sentry nodes to buffer traffic. If a sentry gets crashed by this exploit, your validator stays safe.
  2. Resource Limits: Ensure your systemd service file has Restart=always and appropriate restart delays to prevent a crash loop from completely hanging the OS.
  3. Monitoring: Alert on panic in logs. It's rarely a good sign.

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
5,000
via EtherNodes

Affected Systems

go-ethereum (geth) < 1.16.8

Affected Versions Detail

Product
Affected Versions
Fixed Version
go-ethereum
Ethereum
< 1.16.81.16.8
AttributeDetail
CWE IDCWE-20 (Improper Input Validation)
CVSS Score7.1 (High)
Attack VectorNetwork (P2P)
ImpactDenial of Service (Crash or Resource Exhaustion)
Exploit StatusPoC Available
LanguageGo (Golang)
CWE-20
Improper Input Validation

Improper Input Validation

Vulnerability Timeline

Patch committed to master
2026-01-09
CVE Published / Release v1.16.8
2026-01-13

Subscribe to updates

Get the latest CVE analysis reports delivered to your inbox.