Node2Shell
CIA Risk Posture & Executive Assurance
Compromised Node.js, Bun, or Python services expose cloud environment variables, internal API tokens, and customer payloads.
A single compressed request or your backend fetching data from an untrusted third-party URL can grant full remote
control on stock x86-64 and arm64 builds with ASLR enabled.
Malformed compressed payloads or mismatched build offsets crash runtime processes immediately, taking down APIs and serverless functions.
Edge WAF rules (such as Vercel’s Oct 21 rule) only filter inbound requests; backends remain exposed when fetch() downloads Brotli responses from external URLs.
Stock binaries (e.g., node:24.22.0-slim on x86-64) share identical memory offsets across all deployments, and End-of-Life Node.js 20.x receives no patch.
Broccoli2Shell (a.k.a Node2Shell):
Crafted Brotli-compressed data triggers an out-of-bounds write
in Google’s C Brotli decoder (1.0.3–1.2.0), enabling remote code execution in
Node.js, Bun, .NET, and Python HTTP clients.
Scored 9.2 Critical (CVSS v4.0) by Google CNA and added to CISA KEV, while Microsoft (.NET) and Red Hat score it 8.1 High (CVSS v3.1) and the Node.js security team rates it High. Following Imperva’s initial Linux arm64 demonstration, researchers at
ELLIO confirmed full RCE on stock x86-64
Node.js 24.22.0 binaries under default settings with standard ASLR enabled
(across plain node:http, node:24.22.0-slim running as root,
Express 5.3.0, and Koa 3). Active in-the-wild scanning and
weaponized exploit traffic targeting x86-64 began on October 26, 2026.
Why it’s a risk (Inbound & Outbound)
Inbound Server Risk: Triggered when Express
5.0.0–5.3.0 (express.json(), urlencoded(),
text(), raw()), body-parser (2.0.0–2.3.0),
Koa 3, or ASP.NET Core automatically decompresses an incoming request with
Content-Encoding: br.
Outbound Client Risk: Triggered when Node.js
fetch(), Next.js image optimization
(/_next/image), .NET HttpClient, or Python HTTP libraries
(requests, urllib3,
httpx) download a response from an untrusted URL
that returns Content-Encoding: br.
How to recognize it (Versions, Logs & IoCs)
-
Vulnerable versions: Node.js
22.x < 22.23.4,24.x < 24.22.1,26.x < 26.12.1(Note: End-of-Life Node.js20.xand earlier receive no fix and must be upgraded); Bun<= 1.4.3; .NET8.x < 8.0.33,9.x < 9.0.22,10.x < 10.0.14; PythonBrotli <= 1.2.0. -
In-the-Wild Indicators of Compromise (IoCs):
Block and hunt for exploit traffic from IP
94.154.43.7— observed delivering customx86-64Node.js24.22.0exploit payloads and rated malicious by ELLIO and malicious by Google Threat Intelligence (GTI Score 60/100) — as well as reconnaissance probes identifying asnode2shell-checksending Brotli request bodies. -
In your logs: Unexpected
POSTorPUTrequests usingContent-Encoding: br, or repeated Node.js / Bun / .NET worker crashes (SIGSEGV) when build-specific memory offsets are probed.
How to mitigate it
-
Patch runtimes & containers: Upgrade to
Node.js
22.23.4,24.22.1, or26.12.1(and migrate off EoL Node.js20.x), Bun1.4.4, .NET8.0.33/9.0.22/10.0.14, and PythonBrotli 1.2.1. Rebuild all Docker images that bundle a Node binary. -
Block Brotli request bodies & IoCs at the edge:
Configure your WAF or API gateway to reject incoming
Content-Encoding: brrequests (while keepinggzipanddeflateenabled) and block94.154.43.7andnode2shell-check. Remember that inbound WAF rules do not cover outboundfetch()calls.
| Software / Runtime | Vulnerable Versions | First Fixed Release |
|---|---|---|
| Node.js | 22.x < 22.23.4 · 24.x < 24.22.1 · 26.x < 26.12.1 · 20.x & earlier (EoL, unpatched) | 22.23.4 · 24.22.1 · 26.12.1 |
| Bun | <= 1.4.3 | 1.4.4 (bundles Brotli 1.2.1) |
| Microsoft .NET Runtime | 8.x < 8.0.33 · 9.x < 9.0.22 · 10.x < 10.0.14 | 8.0.33 · 9.0.22 · 10.0.14 |
| Python Brotli / brotlicffi | <= 1.2.0 / <= 1.2.0.x | 1.2.1 · 1.2.1.0 |
| Google Brotli (Upstream C) | 1.0.3 – 1.2.0 | 1.2.1 · 1.1.1 · 1.0.10 |