Yesterday you patched PHP. Today it is Node's turn. On the same October 21 release day that closed out PHP2Shell, the Node.js project also shipped fixes for CVE-2026-111497, a high-severity out-of-bounds write in the Brotli decoder bundled with the runtime. Imperva's Red Team, which named its analysis Node2Shell, demonstrated attacker-supplied code running inside the official vulnerable Node.js image. Ron Masas of Imperva put it best on X: "Liked PHP2Shell? You're gonna love Node2Shell." Nobody on the internet got a break this week.
What happened
On October 21, 2026, Node.js published its October security releases covering the 22.x, 24.x, and 26.x lines. Among them: "Node.js Brotli decoder out-of-bounds write permits remote code execution," rated high. The advisory credits Khai Tran and Sylvie Mayer of OpenAI Codex Security with the report, and Matteo Collina and Antoine du Hamel with the fix. One clarification worth making early: Node2Shell is Imperva's name for its analysis of the flaw, not a second vulnerability, and Node.js itself does not use the name.
How the flaw works
Brotli is a compression format that turns up on both sides of an HTTP exchange in Node. A service can consume a compressed response from another server through the built-in fetch(), or decode an incoming request body through middleware. Both paths feed untrusted bytes into the same native decoder that ships inside Node.js.
A Brotli stream declares the block types it will use as decoding progresses. CVE-2026-111497 is what happens when the stream declares something structurally impossible. Two internal functions mishandle that situation: DecodeBlockTypeAndLength treats invalid input as a request for more input, and DecodeLiteralBlockSwitch discards the result of that check. Instead of failing, the vulnerable decoder keeps decoding with inconsistent internal state and can write past its intended buffer, corrupting memory adjacent to the decoder state. The consequences range from a crash or memory disclosure to arbitrary code execution with the process's privileges. The fixed decoder returns a format error for the invalid transition and hands it back to the caller.
Proof of concept
Imperva's write-up walks a standalone exploit from malformed Brotli data to code running in fresh containers built from the official Node.js 24.22.0 Linux arm64 image. The test application contained no code to create the marker file that appeared after it received the compressed payload. Two entry paths worked:
- Consumed responses. A service using the built-in
fetch()decoded an attacker-controlled Brotli response and ran the code it carried. - Request bodies. Express 5.0.0 through 5.3.0 with body-parser 2.0.0 through 2.3.0, configured with
raw()orjson(), handed incoming Brotli bodies to the same native decoder.
Two honest caveats from the researchers themselves. Execution was intermittent in their setup, and they tested only the Linux arm64 build, not every platform or application configuration. The same inputs on Node.js 24.22.1 were rejected cleanly, with the server still running. Public proof-of-concept code is already on GitHub, and while there was no confirmed in-the-wild exploitation as of October 22 and the flaw is not in CISA's Known Exploited Vulnerabilities catalog, a public PoC tends to shorten the road to scanning.
Who is affected
- Node.js 22.x, 24.x, and 26.x before the October 21 fixes. End-of-life lines are always affected when a security release lands, and Vercel has confirmed Node.js 20 will not receive this fix.
- Anything bundling Google's Brotli library, versions 1.0.3 through 1.2.0, excluding the maintenance fixes 1.0.10 and 1.1.1. Brotli 1.2.1 contains the fix. Bun bundles the vulnerable decoder and fixed it in 1.4.4.
- Apps that decode Brotli an attacker can influence. Express 5 uses body-parser 2.x, which handles Brotli request bodies by default. Express 4 with body-parser 1.x rejects those bodies with a 415, but any code that decompresses untrusted data still reaches the flaw. A bare Node HTTP server does not decode incoming Brotli on its own.
What to do right now
- Patch the runtime. Update to Node.js 22.23.4, 24.22.1, or 26.12.1 or later in each supported line, and Bun to 1.4.4. Rebuild container images and redeploy, since a base image tag can quietly bundle an older runtime. Run
node --versioninside the container that actually serves traffic to verify what you are running. - Handle the Node 20 tail. Node.js 20 is past end of life and will not get this fix. Any remaining workload on it should move to a supported line this week, not eventually.
- Check your dependency paths. Distribution builds that link against system Brotli need the distro's security update, and you should verify which library your application actually loads.
- If you cannot patch tonight, choke the entry points. Reject inbound requests using
Content-Encoding: brbefore decompression, disable Brotli request-body parsing you do not need, and restrict which upstream responses your services auto-decompress, because inbound filtering does nothing for responses your code fetches. Node.js offers no configuration-only fix. These measures only reduce exposure.
Detection signs
Unexpected process exits during decompression and decoder errors are the signals to prioritize on affected runtimes. Neither is reliable on its own, so correlate them with the deployed Node version and the origin of the compressed data.
Why this one matters
The uncomfortable detail sits in the advisory's credit line: the bug was reported by OpenAI Codex Security. One day earlier, the PHP2Shell research showed frontier AI models turning decade-old memory-corruption bugs into working exploits in a week. The runtimes underneath everyday web applications are now being audited by machines, and the same acceleration that helps defenders shortens an attacker's path from bug to exploit. Patching speed is part of your threat model, not a scheduling preference.
The authoritative source is the Node.js security advisory, with the full technical detail in Imperva's research. Both of this week's emergency patches, PHP and Node, landed on the same day. Patch both stacks, then go have the coffee you have earned.