# 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.