On October 21, 2026, Node.js fixed CVE-2026-111497, a critical vulnerability now known as Node2Shell and, since October 24, HTTP2Shell. The vulnerability is in Google’s Brotli library itself, the decoder that unpacks Brotli-compressed data. Node.js shipped the first runtime fix. Bun, Python’s Brotli packages, Envoy, Istio and Electron are also affected because they use the same library.
A crafted compressed stream makes the decoder write data outside the memory set aside for it, known as an out-of-bounds write. That can overwrite data the application relies on, so an attacker can crash the application, leak memory or run attacker code. Public proof-of-concept code was published within 24 hours. AppTrana WAAP blocks the inbound attack path for any backend behind it. Patching is still required to close the paths a WAF cannot see.
Risk Analysis
CVSS 4.0 score of 9.2
Affected versions
Google Brotli 1.0.3 to 1.2.0, and the runtimes and packages that use it
Node2Shell: From Patch to Public PoC in 24 Hours
February 27, 2026
The Brotli fix lands upstream, with no security note.
October 21, 2026
Node.js releases 22.23.4, 24.22.1 and 26.12.1.
October 22, 2026
The CVE is published with a CVSS score of 9.2. Public PoCs appear. They crash and leak memory on standard builds.
October 23, 2026
Researchers demonstrate code execution on the official Node.js 24.22.0 image. Envoy publishes its advisory. Python Brotli 1.2.1 and brotlicffi 1.2.1.0 are released.
October 24, 2026
Bun names the vulnerability HTTP2Shell.
What is Node2Shell (HTTP2Shell)?
Node2Shell is a memory-safety vulnerability in Google’s Brotli decoder library, versions 1.0.3 to 1.2.0. Node.js bundles this library in its zlib module, and many other runtimes, proxies and packages use it.
An attacker crafts a Brotli stream that is deliberately malformed: it declares one type of data block, then asks the decoder to switch block types. The decoder should stop with an error. An unpatched decoder ignores the error and keeps going, so it writes past the end of its buffer. The fix (Brotli commit 0ed4268a) stops decoding with a new error, BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH.
An attacker needs an application to decompress Brotli data that the attacker controls. This can happen in four ways:
Request bodies
The attacker sends a Brotli-compressed request body, marked with the Content-Encoding: br header. Express 5.0.0 to 5.3.0, body-parser 2.0.0 to 2.3.0 and Koa decompress these by default.
Outbound responses
The application calls a server the attacker controls, and the server replies with a Brotli response. Built-in fetch(), Next.js server-side fetch(), axios, node-fetch, got and SuperAgent decompress it automatically. In Python, requests, urllib3, httpx and aiohttp decode Brotli automatically when Brotli or brotlicffi is installed.
Application code
The application passes attacker-supplied files or fields to zlib.brotliDecompress() or an equivalent Brotli call in another language.
Proxies
The application runs behind Envoy or Istio with the Brotli decompressor turned on. The proxy decodes the Brotli data itself, so the attack reaches the proxy before it reaches the application.
Affected and Fixed Versions
| Product | Vulnerable | Fixed |
|---|---|---|
| Google Brotli library | 1.0.3 – 1.2.0 | 1.0.10 / 1.1.1 / 1.2.1 |
| Node.js 22.x | < 22.23.4 | 22.23.4 |
| Node.js 24.x | < 24.22.1 | 24.22.1 |
| Node.js 26.x | < 26.12.1 | 26.12.1 |
| Node.js 20.x, 23.x, 25.x and older | All | No fix (end of life). Upgrade to 22, 24 or 26 |
| Bun | ≤ 1.4.3 | 1.4.4 |
| Python Brotli | ≤ 1.2.0 | 1.2.1 |
| Python brotlicffi | ≤ 1.2.0.x | 1.2.1.0 |
| Envoy (with Brotli decompressor) | Below the fixed versions | 1.36.12 / 1.37.8 / 1.38.6 / 1.39.3 / 1.40.0 |
| Istio (with Brotli decompression) | 1.29.0 – 1.31.1 | 1.29.9 / 1.30.6 / 1.31.2 |
| Ruby brotli gem | < 0.9.1 | 0.9.1 |
Some Linux distributions and runtimes are still waiting for a fix. Red Hat Enterprise Linux 8, 9 and 10, the .NET runtime, the PHP Brotli package, and the Debian and Ubuntu nodejs packages have no patch yet. Amazon Linux 2023 has fixed its brotli and nodejs24 packages, though its nodejs and nodejs20 packages have no fix planned. Debian 12 and 13 and Alpine have also shipped fixed brotli packages.
Keep in mind that Node.js and Bun bundle their own copy of Brotli, so updating the OS package does not protect them. Upgrade the runtime itself.
What Node2Shell Means for Your Web Infrastructure
| Risk | What it means |
|---|---|
| Server takeover | An attacker’s code runs with the permissions of the affected process (Node.js, Bun, Python or Envoy) and can steal data. |
| Stolen credentials | Even when code execution fails, leaked memory can expose database credentials, API keys and cloud tokens. |
| Service outage | Each failed attempt can crash the process and take an API offline. |
| Attack through outbound calls | Webhooks, link previews, crawlers and AI agent tools fetch URLs that other people choose. A malicious server can reply with a crafted Brotli response that no inbound control sees. This applies to Node.js and Python HTTP clients alike. |
How to Detect Node2Shell
Find every Node.js, Bun, Python, Envoy, Istio and Electron runtime, including containers and CI. Then look for these signs from October 21 onwards:
Requests
Any Content-Encoding: br request body, which browsers and API clients do not send. Watch most for bodies over 1 MB or sent chunked (the published PoC is about 23 MB), duplicate Content-Encoding headers, and repeated Brotli requests from one IP.
Outbound traffic
Brotli responses from hosts that users supply, such as webhook targets, link-preview URLs and AI agent tool calls.
Logs
ERR__ERROR_FORMAT_BLOCK_SWITCH (constant BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH, value -17) means a patched runtime rejected an attack attempt. On unpatched servers, look for Brotli decoding errors, SIGSEGV crashes in Node.js, Bun, Python or Envoy, restarts and HTTP 502/503 after a Brotli request.
Host activity
Node.js, Bun, Python or Envoy processes starting sh, bash, curl or wget, and unexpected outbound connections.
A crash alone does not prove exploitation. Check patched servers too, since patching does not remove an earlier compromise.
Node2Shell: Mitigation and Remediation
Upgrade Node.js to 22.23.4, 24.22.1 or 26.12.1, Bun to 1.4.4, Python Brotli to 1.2.1, brotlicffi to 1.2.1.0, and Envoy and Istio to the fixed versions listed above. Rebuild container images with docker build --pull, restart services, and rotate secrets if you find signs of compromise. Until you can patch, these settings reduce exposure:
// Confirm the fix (run in a shell): prints -17 when patched
node -p "require('zlib').constants.BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH"
// Express 5: stop decoding compressed request bodies
app.use(express.json({ inflate: false }));
// axios / got: turn off response decompression
axios.get(url, { decompress: false });
Python: Upgrade Brotli and brotlicffi, or uninstall them where they are optional. requests, urllib3, httpx and aiohttp stop requesting Brotli when neither package is installed.
Envoy and Istio: Upgrade, or turn off the Brotli decompressor until you can.
A WAF blocks the inbound path, but it cannot see Brotli responses your application fetches. Patching is the only complete fix.
AppTrana WAAP Coverage for Node2Shell
AppTrana WAAP customers are protected against inbound Node2Shell attacks on any backend, including Node.js, Bun, Python and Envoy. Protection is in block mode by default, with no action needed.
Emergency rule update (October 22, 2026)
AppTrana blocks Brotli-compressed request bodies (Content-Encoding: br, including variants such as gzip, br) and duplicate Content-Encoding headers before they reach the origin. The rule protects any backend behind AppTrana, including Node.js, Bun, Python, Envoy and Istio. The Indusface security research team released the rules to all AppTrana sites after validating them for false-positive risk.
Continuous monitoring
The 24×7 managed services team tracks Node2Shell rule hits, obfuscated br values and PoC-sized streams across all customers.
Recommended actions for AppTrana customers
Keep applications in Block mode, enable Origin Protection, and upgrade every affected runtime and package. AppTrana protects you while you patch; outbound fetch() responses still need the runtime fix.
Protect Node.js, Bun, Python and Envoy workloads with AppTrana WAAP.
Block inbound Node2Shell attack attempts while your team patches every runtime.
References
- Node.js: October 2026 security releases
- HOL Guard: CVE-2026-111497 technical record
- The Hacker News: Node.js Brotli decoder bug
- Bun: Bun v1.4.4 release notes
- Envoy: Out-of-Bounds Write in Brotli Decompressor (GHSA-3wvj-j6qm-62mr)
- Python Brotli and brotlicffi: GitHub Security Advisory GHSA-9v8h-qqgm-4m35
- Google Brotli: v1.2.1 release
- Red Hat: CVE-2026-111497
- CISA: Known Exploited Vulnerabilities Catalog