~ node –version # if this prints anything older than the fixed lines below, keep reading
Node2Shell: The Brotli Bug That Turned HTTP/2 Into Remote Code Execution
One flaw in a compression library every runtime shares. One crafted stream. No login required. The name is marketing — the bug is real, and it is not in HTTP/2 at all.
CVE-2026-111497 is an out-of-bounds write in Google’s Brotli decoder (c/dec/decode.c), affecting library versions 1.0.3 through 1.2.0 on all platforms. A remote, unauthenticated attacker sends a crafted Brotli-compressed stream and corrupts the decoder’s own state memory — crash, memory disclosure, or, in the worst case, arbitrary code execution with the privileges of the affected process.
The scores disagree with each other, which is normal and worth saying out loud: Google, as the numbering authority, scores it 9.2 (Critical) on CVSS 4.0; GitHub’s advisory scores it 9.8 on CVSS 3.1; the Node.js project rates its own exposure High. NVD still lists it as Undergoing Analysis with no score of its own. Different scorers, same bug — don’t let the number spread confuse the priority.
A Brotli stream declares how many block types each chunk contains. A malicious stream claims one type, then asks to switch to another — an impossible switch. The vulnerable decoder reported that impossible switch as “more input needed” instead of a final error, so the streaming decoder kept queuing bytes into an internal 8-byte buffer and wrote past the end of it, into its own state.
The faulty code dates to 2018. The upstream fix landed in Brotli’s source in February 2026 and sat there for eight months, because nobody knew it was a security fix yet — there was no newer Brotli release to carry it. It shipped on October 21, 2026, and the first public proof-of-concept appeared about five hours later.
Node.js got the nickname first, but the flaw is upstream in Brotli itself, so everything that decodes Brotli needs its own fix. And the worst part of this one is how quietly the decoder gets reached. There are two ways in:
Inbound: your app decodes a request body sent with Content-Encoding: br — Express 5 and body-parser 2.x do this for you. Outbound: your app fetches a URL and the server answers with a Brotli response — Node’s built-in fetch() decodes it automatically, as do Python’s requests, httpx and aiohttp when Brotli is installed, and curl. Most exposed: anything that fetches URLs users give it — webhooks, link previews, crawlers, “call this URL” features.
deps/brotli) inside the binary. Patching the operating system’s libbrotli package does not patch Node.js, and npm audit will not flag it, because it is not an npm package. Check the runtime itself: node --version is the authoritative test; node -p "process.versions.brotli" is inventory only.And the name: it is not a bug in the HTTP/2 protocol. It is a bug in a decoder that HTTP traffic happens to carry. Since the story broke, it has collected three names — Node2Shell (Imperva, who coined it), HTTP2Shell (the wider-impact name), Broccoli2Shell (Wiz). One CVE, three names, zero additional bugs. A reverse proxy in front does not fix the runtime behind it, and Apache’s mod_brotli doesn’t decode by default, so it is largely out of scope.
The same Node.js release fixed nine other CVEs, so this is a good excuse to take the whole security release, not just the Brotli line.
Lab code execution is demonstrated. Imperva ran code on the official Node.js 24.22.0 Linux arm64 image on October 22, via a fetch() response and via Express 5 / body-parser 2 request bodies — it took multiple attempts, and their exploit was not released. Public proof-of-concept code crashes stock builds; reaching a shell on a stock build is the part researchers disagree about.
Real-world exploitation is where the story splits, so here it is unsmoothed. CISA added the CVE to its Known Exploited Vulnerabilities catalog on October 27, 2026, with a federal remediation deadline of November 10 — a KEV listing means CISA has evidence of active exploitation, but CISA does not publish that evidence, and no victim has been named. Honeypot telemetry backs up attempts, not successes: one firm logged a single attempt on October 27 from a US address, rated “confirmed” as an attempt — explicitly not a success — and another firm’s sensors caught in-the-wild traffic carrying a payload built for Node 24.22.0, copied from the public proof-of-concept, which crashed the process in 50 replayed attempts and never reached a shell. First-generation attempt, defective last stage.
So: attempts confirmed, successful compromise of a real target not yet demonstrated. Patch like it’s real anyway — KEV listing plus public proof-of-concept plus a one-day patch-to-PoC gap is not a combination to sit on.
1. Check every Node deployment against the fixed lines — the running process, not the config file or the Docker tag. node --version, or run the binary inside the image.
2. Rebuild container images on a patched base and restart long-running processes and workers, so the patched binary actually loads. Updating Express, body-parser or a WAF rule does not replace the runtime fix — the vulnerable memory handling is in the bundled decoder, not your JavaScript.
3. Patch the rest separately: OS libbrotli, Python packages, Bun, .NET, Envoy, Istio. One fix does not cover the others, because every runtime carries its own copy.
4. If you cannot patch yet, disable Brotli decoding of untrusted data wherever you can.
5. Watch for Node.js processes spawning shells or downloading tools, and for unusual requests carrying Content-Encoding: br.
Oct 14 — Node.js pre-announces the release. Oct 21 — Node.js ships 22.23.4, 24.22.1, 26.12.1; Brotli ships 1.0.10, 1.1.1, 1.2.1; first public proof-of-concept lands hours later. Oct 22 — Imperva demonstrates code execution; Google’s CVE record publishes at 9.2. Oct 23 — the wider impact gets the HTTP2Shell name. Oct 25 — Microsoft ships .NET fixes. Oct 26 — PHP ships Windows rebuilds. Oct 27 — CISA adds it to KEV; honeypots log attempts. Nov 10 — federal remediation deadline.
Node.js October 2026 security releases · Wiz: Broccoli2Shell · SecurityWeek: KEV listing and honeypot attempts · Sysdig: timeline and detection · Related on this site: PHP2Shell: two bugs that turned requests into shells — same week, same pattern, a memory bug in a component everybody shares.
