Node2Shell (CVE-2026-111497): a Brotli decoder bug lets crafted compressed data run code in Node.js, Bun and Python apps. How to check and patch.
Your clients' web servers unzip things all day: every compressed request body and every compressed response they fetch from another server goes through a decoder first. In late October we learned that one of those decoders, Google's Brotli, could be fed a malformed stream that writes past the end of its own memory, and that the fix had been sitting in Brotli's public source code since February while no release carried it.
The bug is CVE-2026-111497, nicknamed Node2Shell. It lives in the copy of Brotli bundled inside Node.js, Bun, Python packages, Envoy and more. Each of those programs ships its own copy, so each one needs its own patch.
fetch(), the Python Brotli package (1.2.0 and earlier, per PYSEC-2026-4322) and Bun.Node2Shell is a memory-corruption bug in Google's Brotli decoder: a malformed compressed stream makes the decoder write past the end of an internal buffer. In plain terms, Brotli is a compression format, like a tighter ZIP for web traffic. The decoder is the part that unpacks it.
The Node.js advisory explains the mechanism. "An invalid block switch was reported as a temporary need for more input instead of a permanent format error, so the streaming decoder kept appending input bytes to an eight-byte internal buffer." Picture a mail slot that, instead of rejecting a parcel that is obviously the wrong shape, keeps shoving it in until it breaks the wall behind. The result, says Node.js, "can lead to a crash, disclosure of process memory, or remote code execution."
Node.js credits Khai Tran and Sylvie Mayer of OpenAI's Codex Security team with the report. Severity labels differ by source, all reported by The Hacker News: Google rates it 9.2 (critical) on CVSS 4.0, Node.js calls it high, and Red Hat rates it 8.1. Treat it as critical, because the worst outcome is code running with the permissions of the app.
According to The Hacker News, the fix entered Brotli's source code on February 27, but no Brotli release shipped it until October 21. Brotli v1.2.1 is that release, and its notes read "CVE-2026-111497: out-of-bounds write permits remote code execution." Anyone reading Brotli's commit history could have spotted the change, so watch for signs of trouble going back further than the October disclosure.
Any program that bundles the vulnerable Brotli decoder and decompresses data an attacker controls is affected. The main ones your clients run:
express.json(), express.urlencoded(), express.text(), express.raw()) decode Content-Encoding: br request bodies. Imperva ran code through Express 5.0.0–5.3.0 and body-parser 2.0.0–2.3.0.fetch() to read a compressed response from another server. Imperva reproduced code execution on this path too.Brotli 1.2.0 and earlier (fixed in 1.2.1) and brotlicffi 1.2.0.x and earlier (fixed in 1.2.1.0), when an HTTP client or service decodes Brotli.One reassuring detail: Imperva notes that "a bare Node.js HTTP server does not decode incoming Brotli bodies just by receiving them." Exposure needs middleware or code that actually decompresses.
No in-the-wild exploitation has been reported as of October 25, 2026. The Hacker News reports that CISA's October 23 assessment lists exploitation as "none." Imperva's demonstration is unreleased, worked only on one Linux arm64 build, and "took multiple attempts in its setup." That is a window to patch in, not a reason to wait.
Check the runtime version inside every host, container and image, plus every Express and Python dependency. Run these per host, as root:
mkdir -p /root/ir-brotli
journalctl --since 2026-02-27 > /root/ir-brotli/journal.txt
dmesg -T > /root/ir-brotli/dmesg.txt
docker image ls --digests > /root/ir-brotli/images.txt
/var/lib/docker:find / \( -path /proc -o -path /sys \) -prune -o -type f -name node \
-perm -u+x -print 2>/dev/null | while read b; do echo "$b $("$b" --version)"; done
for c in $(docker ps -q); do echo "$c $(docker exec "$c" node --version 2>/dev/null)"; done
docker image ls --format '{{.Repository}}:{{.Tag}}' | grep -v '<none>' | while read i; \
do echo "$i $(docker run --rm --entrypoint node "$i" --version 2>/dev/null)"; done
find / \( -path /proc -o -path /sys \) -prune -o \
-path '*node_modules/body-parser/package.json' -print 2>/dev/null | xargs grep -H '"version"'
Brotli-1.2.0.dist-info. The Hacker News warns Dependabot may not flag them, so check by hand:find / \( -path /proc -o -path /sys \) -prune -o -iname 'brotli*.dist-info' -print 2>/dev/null
Check Bun, Istio and Envoy where they are installed: command -v bun && bun --version, istioctl version and envoy --version. For Istio and Envoy, the affected versions matter only where Brotli decompression is switched on.
Look for crashes during decompression. Imperva says unexpected process exits and decoder errors can help you prioritize, but neither proves exploitation alone. Check kernel logs with journalctl -k --since 2026-02-27 | grep -i segfault and container restarts with:
docker inspect -f '{{.Name}} {{.RestartCount}}' $(docker ps -q)
Repeat steps 2–6 on CI runners and build servers. Vercel's advisory names CI runners, self-built containers and self-hosted Next.js as places to upgrade.
Upgrade the runtime or package, restart it, and rebuild the images that carry it. A running process keeps the old decoder until it restarts.
server block:if ($http_content_encoding ~* "br") { return 415; }
On Python hosts that cannot upgrade yet, pip uninstall -y brotli brotlicffi makes clients fall back to gzip and deflate, per The Hacker News. Removing br from the Accept-Encoding header is not enough, because a server can send Brotli anyway. Edge rules also cannot see responses your clients' apps fetch from other servers; Vercel says only the runtime patch covers that path.
3. Patch. Node.js to 22.23.4, 24.22.1 or 26.12.1; move Node.js 20 apps to 22.x or 24.x. Bun to 1.4.4. Python Brotli to 1.2.1 and brotlicffi to 1.2.1.0. Istio to 1.29.9, 1.30.6 or 1.31.2; Envoy to 1.40.0, 1.39.3, 1.38.6, 1.37.8 or 1.36.12, per The Hacker News.
4. Rebuild and redeploy every container image on a patched base image, then rerun steps 2–4 of the check list to confirm no old version remains.
The hard part of Node2Shell isn't the patch. It's knowing which of your clients' internet-facing apps run Node.js, Express or Python at all, and which ones nobody has touched since Node.js 20 went end-of-life. Version inventories cover the servers you know about; the forgotten staging API is the one that bites.
KinoSec runs autonomous web app and external network pentests for each client: reconnaissance to map what is actually reachable from the internet, finding vulnerabilities, chaining exploits across surfaces, and a findings report with remediation you can hand straight to the client. Pair that external view with the version checks above, and you can tell every client both what to patch and what they didn't know they were exposing.
Node2Shell is CVE-2026-111497, a memory-corruption bug in Google's Brotli decoder: a malformed compressed stream makes the decoder write past the end of an internal buffer. Node.js says it "can lead to a crash, disclosure of process memory, or remote code execution." It affects Node.js 22.x, 24.x and 26.x, Bun 1.4.3 and earlier, the Python Brotli and brotlicffi packages, and Envoy or Istio where Brotli decompression is switched on.
First preserve evidence: save journalctl and dmesg -T output and docker image ls --digests before restarting anything. Then print the version of every Node.js binary on each host and inside each container with docker exec <id> node --version, and check images that aren't running with docker run --rm --entrypoint node <image> --version. Finally, search for node_modules/body-parser/package.json (version 2.x means Express 5 body parsing) and brotli*.dist-info folders for the Python packages.
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 and brotlicffi to 1.2.1.0. Restart every service and rebuild every container image on a patched base, because a running process keeps the old decoder until it restarts. Node.js 20 gets no fix, so move those apps to 22.x or 24.x.
No in-the-wild exploitation has been reported as of October 25, 2026, and The Hacker News reports that CISA's October 23 assessment lists exploitation as "none." Imperva ran attacker code on an official Node.js 24.22.0 Linux arm64 build through both fetch() and Express 5 request bodies, but the exploit took multiple attempts and has not been released.
KinoSec runs autonomous web app and external network pentests that map what each client exposes to the internet, find vulnerabilities, chain exploits across surfaces and report findings with remediation. Use it alongside the version checks above, so you know which client apps are reachable as well as which ones need the patch.