# Remote DoS via ECIES Decryption Panic in Geth
## Overview
In January 2026, the Geth team released a [security fix](https://github.com/ethereum/go-ethereum/commit/638741b082bec27b94034d43af93269dad665606) addressing a DoS vulnerability in the ECIES decryption logic used in Ethereum p2p communication.
The issue is tracked as [GHSA-mr7q-c9w9-wh4h](https://github.com/ethereum/go-ethereum/security/advisories/GHSA-mr7q-c9w9-wh4h) and allows a remote peer to crash a Geth node by sending a specially crafted encrypted p2p message. The crash is caused by an out-of-bounds slice access during ECIES symmetric decryption, resulting in a runtime panic.
Vulnerability Summary:
- **Impact**: Remote DoS (node crash)
- **Attack Vector**: Ethereum p2p networking layer
- **Severity**: High (unauthenticated remote crash)
- **Affected**: Geth and downstream implementations utilizing the affected ECIES logic
- **Fix**: Corrected minimum-length validation before decryption
- **Reporter**: DELENE TCHIO ROMUALD (via the Ethereum Foundation Bug Bounty Program)
All Geth users are strongly recommended to upgrade. OP-Geth released a corresponding [patched version](https://github.com/ethereum-optimism/op-geth/releases/tag/v1.101605.0) as well.
## Background: ECIES in Ethereum P2P
### P2P handshake and encrypted messaging
Ethereum nodes communicate over a custom peer-to-peer protocol known as RLPx.
RLPx establishes encrypted peer-to-peer connections using an ECIES-based handshake over secp256k1.
### ECIES message structure (simplified)
An ECIES ciphertext in Geth has the following logical structure:
```
ciphertext =
ephemeral_public_key (65 bytes)
|| encrypted_message (variable length)
|| mac (32 bytes)
```
The encrypted_message itself is expected to be:
```
encrypted_message =
IV (blockSize bytes, AES = 16) || encrypted_payload
```
This implies a **minimum required length** for the encrypted message part.
### Trust boundary
Importantly, all ECIES ciphertexts are **fully attacker-controlled input**:
- Any remote peer can send ECIES-encrypted messages
- The receiver must treat all ciphertexts as untrusted and potentially malformed.
- Length validation is therefore security-critical
As a result, any unchecked assumption in ECIES parsing or decryption code can directly translate into a remote denial-of-service condition.
## Root Cause Analysis
### The vulnerable code path
The vulnerability stems from an out-of-bounds slice access in the ECIES symmetric [decryption helper](https://github.com/ethereum/go-ethereum/blob/1022c7637dcd0cc063105f2709cadf0b88c50ae9/crypto/ecies/ecies.go#L222):
```
func symDecrypt(params *ECIESParams, key, ct []byte) ([]byte, error) {
c, _ := params.Cipher(key)
ctr := cipher.NewCTR(c, ct[:params.BlockSize]) // ← panic here
...
}
```
This code assumes:
```
len(ct) >= params.BlockSize
```
However, this assumption was **not enforced** by the caller.
### Incorrect length check
In PrivateKey.Decrypt, the pre-decryption length [check](https://github.com/ethereum/go-ethereum/blob/b9f3a3d964ed3d31e710ec7dd66da9181477ecb2/crypto/ecies/ecies.go#L293) was effectively:
```
len(ciphertext) >=
ephemeralPubKeyLen (65)
+ macLen (32)
+ 1 // incorrect
```
This allowed ciphertexts where the encrypted message part was **shorter than one AES block** (16 bytes).
As a result:
- The malformed ciphertext passed validation
- symDecrypt was invoked
- ct[:params.BlockSize] caused a slice-out-of-bounds panic
- The node crashed
The fix replaces the incorrect + 1 check with:
```
+ params.BlockSize
```
ensuring the IV is always present.
## Minimal Proof of Concept
To demonstrate the issue, we constructed a minimal PoC that:
- Uses a valid ECIES ephemeral key
- Computes a correct MAC
- Intentionally sets the encrypted message length to less than 16 bytes
This is sufficient to trigger the panic on vulnerable versions. The full PoC source code is available at:
https://github.com/qzhodl/CVE-2026-22862
## Key Takeaways
This vulnerability illustrates several important lessons for client and protocol developers:
### Length checks must match downstream assumptions
Every slice operation (x[:N]) encodes a hidden precondition:
```
len(x) >= N
```
If that assumption is enforced in a different function or layer, the validation must be exact, not approximate.
### Cryptographic correctness ≠ memory safety
Even though:
- The ECIES math was correct
- The MAC was verified
- The ciphertext was “cryptographically valid”
the implementation still crashed due to a simple bounds error.
### Panic as a DoS Vector
In network-facing code:
- A panic is equivalent to a remote crash
- All panics must be treated as potential DoS vulnerabilities
Defensive programming is especially critical in cryptographic and parsing code.