The Fix Was Public for Months. The Patch Wasn't.

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.

TL;DR

  • What happened: Node.js disclosed CVE-2026-111497 on October 21, 2026, a Brotli decoder out-of-bounds write that can lead to remote code execution in Node.js 22.x, 24.x and 26.x.
  • Am I exposed: Client apps are exposed if they decode attacker-controlled Brotli data. That covers Express 5 body parsers, Node's built-in fetch(), the Python Brotli package (1.2.0 and earlier, per PYSEC-2026-4322) and Bun.
  • What to do: Upgrade Node.js to 22.23.4, 24.22.1 or 26.12.1, Bun to 1.4.4 and Python Brotli to 1.2.1. Then restart every service and rebuild every container image.
  • Impact: No in-the-wild exploitation is reported, but Imperva ran attacker code on an official Node.js 24.22.0 build, though it took several attempts.

What is Node2Shell (CVE-2026-111497)?

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.

Why "the fix was public for months" matters

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.

Which software is affected?

Any program that bundles the vulnerable Brotli decoder and decompresses data an attacker controls is affected. The main ones your clients run:

  • Node.js 22.x, 24.x and 26.x before 22.23.4, 24.22.1 and 26.12.1. Node.js 20 is end-of-life and gets no fix, Vercel notes.
  • Express 5 apps. Express 5's body parsers (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.
  • Anything using Node's fetch() to read a compressed response from another server. Imperva reproduced code execution on this path too.
  • Bun 1.4.3 and earlier (fixed in 1.4.4), per The Hacker News.
  • Python 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.
  • Envoy and Istio, only where Brotli decompression is switched on. Istio's advisory lists 1.29.0–1.29.8, 1.30.0–1.30.5 and 1.31.0–1.31.1.

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.

Is CVE-2026-111497 being exploited?

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.

How do I check if my clients are exposed?

Check the runtime version inside every host, container and image, plus every Express and Python dependency. Run these per host, as root:

  1. Preserve evidence first. Restarting a service wipes its running state, so save logs and an image list before you patch:
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
  1. Find every Node.js binary on the host and print its version. Package lists miss copies bundled in apps and container layers; this search also reaches Docker's layers under /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
  1. Check every running container:
for c in $(docker ps -q); do echo "$c $(docker exec "$c" node --version 2>/dev/null)"; done
  1. Check images that aren't running yet, so a later deploy doesn't bring the bug back:
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
  1. Find Express 5 body parsing (body-parser 2.x is the version Imperva exploited):
find / \( -path /proc -o -path /sys \) -prune -o \
  -path '*node_modules/body-parser/package.json' -print 2>/dev/null | xargs grep -H '"version"'
  1. Find the Python packages. The folder name carries the version, for example 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
  1. 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.

  2. 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.

How do I fix CVE-2026-111497?

Upgrade the runtime or package, restart it, and rebuild the images that carry it. A running process keeps the old decoder until it restarts.

  1. Preserve evidence (step 1 above) before anything restarts.
  2. Contain while you schedule the upgrade. Reject incoming Brotli request bodies at the edge. In nginx, inside the 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.

Where KinoSec fits

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.

Frequently Asked Questions

What is Node2Shell (CVE-2026-111497)?

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.

How do I check if my clients are exposed to CVE-2026-111497?

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.

How do I fix CVE-2026-111497?

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.

Is CVE-2026-111497 being exploited in the wild?

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.

Can KinoSec help MSPs with bugs like Node2Shell?

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.