What happened
On October 21, 2026, Node.js released versions 22.23.4, 24.22.1 and 26.12.1 to fix vulnerability CVE-2026-111497, immediately nicknamed Node2Shell. It is rated 9.2 out of 10 (CVSS 4.0) in Google's CVE record; Node.js, for its part, classifies it as "high".
The flaw is not in Node.js's own code, but in Brotli, the compression algorithm created by Google that compresses a large share of web traffic (Content-Encoding: br header). Node.js ships its own copy, like a multitude of other software.
The mechanism fits in one sentence. Faced with a deliberately malformed stream, the Brotli decoder (versions 1.0.3 to 1.2.0) mistakes a format error for a simple lack of data, and keeps writing into an internal 8-byte buffer… beyond its bounds. The extra bytes overwrite the neighboring memory.
Who found it, and how
The CVE record credits Khai Tran and Sylvie Mayer, from the OpenAI Codex Security team, which relies on AI agents to audit code. Exploitability was then demonstrated by Ron Masas (Imperva), and the impact on the Python ecosystem analyzed by Aikido.
The story has an ironic side: the fix had been in Brotli's source code since February 27, 2026. It had not been identified as a security fix, and no released version included it. For almost eight months, all the software embedding Brotli remained vulnerable without knowing it.
- October 14: Node.js announces a high-severity security release.
- October 21: fixed Node.js versions in the morning, then Brotli 1.0.10, 1.1.1 and 1.2.1 in the evening. A first GitHub repository dedicated to the flaw appears about five hours after the fixes.
- October 22: the CVE is published and the Python packages are fixed. Imperva achieves code execution on the official Node.js 24.22.0 Docker image (Linux ARM64), after several attempts.
- October 23: security advisory for the Envoy proxy; OpenAI publicly announces its discovery.
- October 25: Wiz publishes its exposure figures.
How it spread
No wave of attacks yet: what has spread is the list of affected software. Hence the successive nicknames, Node2Shell, then HTTP2Shell and Broccoli2Shell.
- Node.js 22, 24 and 26 before the fix, and the end-of-life versions 20, 23 and 25, which will not be fixed. Electron applications and standalone Node executables ship their own engine.
- Bun before version 1.4.4.
- Python: the Brotli and brotlicffi packages, which requests, urllib3, httpx, aiohttp or Scrapy use automatically as soon as they are installed, even without an explicit import.
- Go: the andybalholm/brotli library before version 1.2.7.
- Cloud infrastructure: the Envoy proxy, the Istio service mesh, curl and libcurl depending on the linked Brotli version, and Linux distributions that use the system Brotli library.
According to Wiz, 91% of the cloud environments analyzed contain vulnerable resources, and 82% publicly expose Node.js instances. The good news: Apache and NGINX do not decompress incoming Brotli in their default configuration.
As of October 23, no exploitation had been confirmed in the wild, and the flaw was not in CISA's catalog of known exploited vulnerabilities. Public proofs of concept, however, already crash servers.
The risks
- Denial of service. This is the easiest consequence to achieve: a single malformed stream can bring down the Node.js process. Even a failed code execution attempt can take your service down.
- Memory leak. Vercel reports memory disclosure on unpatched versions: secrets, data from other requests.
- Code execution. Demonstrated in the lab on an official image, not yet reliable, but exploits are progressing fast. The code then runs with the privileges of the Node.js service: opening a shell, crypto mining, theft of the container's secrets and cloud tokens.
Why it is dangerous: the door is often already open
Your application does not need to use Brotli deliberately to be exposed. Three paths lead to the decoder:
- Incoming requests. Express 5 and body-parser 2.x automatically decompress request bodies sent with
Content-Encoding: br. Any client can therefore send the booby-trapped stream to your API. - Responses you receive.
fetch()automatically decompresses Brotli responses. A malicious or compromised server (a third-party API, a webhook, a URL supplied by a user) can attack your application through its response. - Direct code. Any call to
zlib.brotliDecompress()orcreateBrotliDecompress()on untrusted data.
Some researchers believe the real impact will be limited to denial of service. For a production API, that is already a serious incident. Treat the flaw as critical.
Available fixes
- Node.js 22: 22.23.4 · Node.js 24: 24.22.1 · Node.js 26: 26.12.1, or a later version of the same branch.
- Node.js 20, 23 and 25: end of life, no fix. Migrate to an LTS version, 22 or 24.
- Bun: 1.4.4.
- Brotli (C library): 1.0.10, 1.1.1 or 1.2.1.
- Python: Brotli 1.2.1 and brotlicffi 1.2.1.0.
- Go: andybalholm/brotli 1.2.7.
- Envoy: 1.37.8, 1.38.6, 1.39.3 or 1.40.0 · Istio: 1.29.9, 1.30.6 or 1.31.2.
How to apply them, step by step
- 1. Take inventory. Run
node --versionon servers, build machines and CI runners, anddocker run --rm <image> node --versionfor each image. Find the entry points withnpm ls express body-parserand a search forbrotliDecompressin your code and dependencies. - 2. Update Node.js. With nvm:
nvm install 24.22.1 && nvm alias default 24.22.1. On Debian or Ubuntu with the NodeSource repository:sudo apt update && sudo apt install --only-upgrade nodejs. With Docker: switch to a fixed tag, for examplenode:24.22.1-alpineor later, rebuild withdocker build --pulland redeploy. Some package managers shipped the fix several hours late: check the version actually installed. - 3. Update the rest of the chain. Python:
pip install -U "brotli>=1.2.1" "brotlicffi>=1.2.1.0". Bun:bun upgrade. Go:go get github.com/andybalholm/brotli@v1.2.7. System: your distribution's security updates for libbrotli. - 4. Restart and redeploy.
pm2 restart allorsystemctl restartfor your services, redeployment of serverless functions, rebuilding of Electron applications and standalone executables. - 5. Check that the fixed version is really the one running in production, not just the one on the development machine.
If you cannot update immediately:
- reject
Content-Encoding: brat the entrance, on your proxy. With NGINX:if ($http_content_encoding ~* "br") { return 415; }; - in Express, disable body decompression with
express.json({ inflate: false }), bearing in mind that this also refuses gzip: test your clients; - restrict the destinations of server-side
fetch()calls and reject Brotli responses from hosts you do not control. Removingbrfrom theAccept-Encodingheader is not enough: a malicious server can ignore it; - run Node.js as an unprivileged user, move secrets out of environment variables where possible, and watch for crashes followed by a shell being launched.
Our takeaways
Your invisible dependencies are your attack surface. Nobody installs Brotli on purpose, and yet it is everywhere. A software bill of materials (SBOM) lets you answer the question "are we exposed?" in a few minutes.
A fix can lie dormant for months. This one had been waiting since February. Tracking your dependencies' versions matters as much as following security announcements.
AI is hunting for flaws, on both sides. In the same week, PHP2Shell and Node2Shell were found by AI-assisted researchers. The pace of patching has to keep up.
Your APIs run on Node.js, your data processing on Python, and you do not know which versions are actually in production? We inventory your dependencies, update your images and CI/CD pipelines, and set up monitoring that warns you before the next alert. Tell us about your project.
Sources: Node.js, Google's CVE record, Wiz, Aikido, Imperva, Sysdig, SecureLayer7 (advisories published October 21 to 25, 2026).