Header image: developer at a laptop with dual monitors. Photo: Christina Morillo / Pexels.
CVE-2026-111497 is an out-of-bounds write in Google’s Brotli decoder. Node.js rates the impact on its runtime as High and says it permits remote code execution. Google, as the CVE Numbering Authority, scores the library flaw 9.2 on CVSS 4.0. The same decoder ships inside Bun, Envoy, Istio (when Brotli decompression is enabled), and anything else that links or embeds a vulnerable Brotli build.
This is not an npm brotli package hunt. The bug lives in the runtime or proxy binary. Bumping a line in package.json and redeploying the same Node or Bun image does nothing.
Versions below were checked against official advisories on October 26, 2026 (America/New_York). If a vendor ships a newer patch after that date, take the vendor page over this article.
Who this bites
You are in scope if any of these are true:
- You run Node.js 22.x, 24.x or 26.x below the fixed releases, or any end-of-life Node line (20.x and older get no upstream fix).
- You run Bun below 1.4.4, including apps built with
bun build --compileon an older Bun. - You run Envoy or Istio with the Brotli decompressor configured (EnvoyFilter or equivalent). Envoy’s advisory is clear: impact is for deployments that have Brotli decompression configured.
- Your app decompresses Brotli it did not create: inbound
Content-Encoding: brbodies (Express 5 / body-parser 2.x style),fetch()ofbrresponses,node:zlibbrotli APIs, or Bun’sDecompressionStream("brotli").
You still want the patched runtime even if you only serve br responses. Serving compressed responses uses the encoder path; the vulnerable code is the decoder. But the decoder stays in the binary, and the next middleware change or outbound fetch can turn a “we only compress” shop into an exposure overnight. Patch when you can. Prioritize shops that decompress untrusted input first.
Small shops get hit the same way large ones do: a Vercel/Fly/Render container still on last month’s Node image, a Bun CLI tool that previews URLs, a home-lab Istio mesh with a copy-pasted EnvoyFilter that turns on Brotli, or a webhook worker that fetches customer-supplied URLs.
If you already lived through our PHP2Shell version check, the pattern rhymes. The engine under the app is what needs updating, not the app’s dependency lockfile alone.
What fails if you only bump package.json
Three failure modes show up over and over.
1. The decoder is compiled into the runtime. Node.js bundles Google’s Brotli under deps/brotli. Bun’s advisory GHSA-663w-cv8g-jj2p says Bun 1.4.3 and earlier bundle an affected Brotli (1.2.0) and that fetch, node:zlib, and DecompressionStream pass data to it. Changing an npm package named brotli does not replace that C library.
2. Transparent decode hides the call site. You may never write brotliDecompress in your code. Node’s HTTP stack and Bun’s fetch decode Content-Encoding: br for you. Express 5 and body-parser 2.x can accept Brotli request bodies. The Node.js advisory states that an attacker who can supply Brotli data that an application decompresses with node:zlib can corrupt process memory — crash, disclosure, or remote code execution.
3. Containers and compile artifacts freeze the old binary. A patched host Node install does not fix a Docker image that still says FROM node:24.22.0. A bun build --compile executable embeds the runtime it was built with; Bun’s advisory says it stays affected until rebuilt with 1.4.4+. Single executable applications and snapshot builds on Node have the same class of problem: the process that is running is what matters, not the version on the build laptop.
Distribution packages add a fourth wrinkle. Some Linux Node packages link system libbrotli. In that case you need the distro’s Brotli (or Node) security update, and node -v alone may not tell you whether the decoder was backported. Check the package changelog for CVE-2026-111497 the same way you would for any other distro security fix.
First fixed releases verified against vendor advisories on Oct 26, 2026 (America/New_York). Graphic: Ctrl Alt Orion.
Am-I-affected checklist
Work top to bottom. Stop when you have a clear yes or no for each runtime you actually run.
1. Inventory Node and Bun versions (hosts and containers)
On every host and in every running container:
node -v
bun -v
In Docker / Kubernetes, do not trust the Dockerfile alone. Exec into the running workload or inspect the image:
docker run --rm your-image:tag node -v
# or
kubectl exec -it deploy/your-api -- node -v
Fixed Node lines (official October 21, 2026 security releases):
| Line | First fixed |
|---|---|
| 22.x | 22.23.4 |
| 24.x | 24.22.1 |
| 26.x | 26.12.1 |
Bun: 1.4.4 or later (GHSA-663w-cv8g-jj2p; affected >= 1.0.21, < 1.4.4).
EOL Node: The Node.js project states that end-of-life versions are always affected when a security release occurs. There is no 20.x / 18.x upstream fix. Plan an upgrade to a supported line, then take the fixed patch on that line.
2. Ask whether anything decompresses untrusted Brotli
You are on the high-priority path if any of these are true:
- Public HTTP API accepts request bodies with
Content-Encoding: br(or a reverse proxy forwards them into a framework that auto-decompresses). - Code calls
fetch()(Node or Bun) against URLs you do not fully control — link previews, webhooks that pull remote content, user-supplied feeds, AI agents that browse. - Code calls
zlib.brotliDecompress/brotliDecompressSync/createBrotliDecompress, or Bun/DecompressionStreamwith the brotli format, on data from outside your trust boundary.
Serving Content-Encoding: br on your responses is not the same as decompressing attacker input. Still patch. Deprioritize relative to inbound/outbound decompress paths.
3. Check Envoy / Istio only if Brotli decompress is on
Envoy (GHSA-3wvj-j6qm-62mr): patched in 1.40.0, 1.39.3, 1.38.6, 1.37.8, and 1.36.12. The advisory lists affected builds including v1.39.2, v1.38.5, v1.37.7 and v1.36.11. Impact: “Envoy deployments that have Brotli decompressor configured.” Note that 1.36.12 includes the fix but the 1.36 branch is unsupported — move to a supported branch when you can.
Istio (ISTIO-SECURITY-2026-007): upgrade to 1.31.2, 1.30.6, or 1.29.9. The bulletin says users who enable Brotli decompression (for example with an EnvoyFilter) should upgrade. 1.29 reached end of life on October 15, 2026; 1.29.9 is the final 1.29 release — plan a move to 1.30+.
If you never enabled the Brotli decompressor, Envoy/Istio are lower urgency for this CVE, but the Istio bulletin also ships unrelated authz and ambient-mode fixes worth taking on their own schedule.
4. Confirm upstream Brotli if you vendor it yourself
NVD / the CVE description: Google Brotli 1.0.3 through 1.2.0 affected; fixed in 1.0.10, 1.1.1, or 1.2.1. The v1.2.1 release notes list CVE-2026-111497 as a security fix. Anything that statically links those vulnerable builds needs a rebuild against a fixed release.
Runtime below fixed + untrusted decompress = high priority. Serving br alone still warrants a patch. Diagram: Ctrl Alt Orion.
Patch order and interim Content-Encoding: br reject
Do this in order. Do not skip the restart.
Patch order
- Internet-facing services that decompress inbound
bror fetch untrusted URLs. Upgrade Node / Bun / Envoy / Istio to a fixed release. - Rebuild every container image and every
bun build --compile/ SEA artifact from the new runtime. Push and redeploy. A running process keeps the old decoder in memory until it is replaced. - Internal workers and cron jobs that
fetchor brotli-decompress untrusted data — same upgrade and rebuild. - Proxies that only compress responses — still upgrade on the next maintenance window; do not leave them on a known-vulnerable decoder forever.
- EOL Node hosts — no cherry-pick from upstream. Move to 22/24/26, then to the fixed patch. Same story we hammered for WordPress LFI patching: staying on a dead line is a business decision with a security price.
Verify after deploy:
node -v # expect >= 22.23.4 / 24.22.1 / 26.12.1 on that line
bun -v # expect >= 1.4.4
For Envoy/Istio, confirm the proxy version your mesh actually runs (istioctl / envoy --version), not only the Helm chart’s appVersion field you meant to bump.
Interim stopgap: reject br if you cannot patch yet
If a rebuild is blocked today, shrink the attack surface at the edge.
At a reverse proxy (nginx example concept): reject requests that advertise Brotli encoding before they reach the app. Exact directive names differ by proxy; the idea is the same — do not forward Content-Encoding: br (and, where you control Accept-Encoding negotiation outbound, stop advertising br) until the runtime is fixed.
In Node middleware (conceptual): reject inbound requests whose Content-Encoding includes br with 415 or 400 before body-parser / framework decompression runs.
For Bun fetch: the Bun advisory documents a per-request workaround — pass decompress: false so that request does not send Accept-Encoding: br and does not decode the response. That is request-scoped, not process-wide. There is no process-wide workaround for affected Bun versions per GHSA-663w-cv8g-jj2p.
For Node fetch of untrusted URLs: there is no standard switch to disable Brotli decode. Upgrade the runtime.
Rejecting br can break clients that only speak Brotli, and it does nothing for code paths that call zlib brotli APIs directly on attacker bytes. Treat it as a stopgap, same class of advice as a WAF rule during PHP2Shell: useful while you schedule the real fix, not a substitute.
Field notes
Broader hygiene that still applies after this CVE: know who owns runtime upgrades in your stack, keep container base images on a short leash, and treat “we only compress responses” as a temporary comfort, not a permanent exception. For the business-side framing of patch urgency and vendor risk, see our ConnectWise / Storm-0940 checklist and small-business data security notes — different incidents, same lesson that standing access and unpatched engines outrank dashboard green lights.
Next steps
- Today: Run
node -v/bun -von every host and every production image. Compare to 22.23.4 / 24.22.1 / 26.12.1 and Bun 1.4.4+. - Today: List services that accept
brbodies orfetchuntrusted URLs. Those patch first. - This week: Upgrade, rebuild images and compile artifacts, redeploy, restart. Confirm the running process version.
- If blocked: Reject inbound
Content-Encoding: brat the proxy or middleware; for Bun, usedecompress: falseon riskyfetchcalls. Schedule the real upgrade. - If on EOL Node: Start the upgrade to a supported line. There is no official 20.x fix for this CVE.
- Envoy/Istio users: Confirm whether Brotli decompression is configured; if yes, move to 1.40.0 / 1.39.3 / 1.38.6 / 1.37.8 (Envoy) or 1.31.2 / 1.30.6 / 1.29.9 (Istio), and plan off 1.36 / 1.29 if you are still there.
Do not wait for a dramatic breach write-up. The condition is already public: unpatched decoder + untrusted Brotli data. Close that condition.
Quick verify commands after redeploy
After the new images are live, confirm the running binary, not the tag you intended:
# Node app container
kubectl exec -it deploy/api -- node -v
# Bun
kubectl exec -it deploy/worker -- bun -v
# Envoy sidecar / gateway
kubectl exec -it deploy/my-gateway -c istio-proxy -- envoy --version
If your platform hides a shell, pull the image digest your deployment actually references and run node -v in a one-off container from that digest. Tag drift (:latest, floating minor tags) is how shops think they patched and still run 24.22.0.
For distro Node packages, also check the Brotli/node changelog for CVE-2026-111497 after the OS update, then restart the service unit or container so workers reload the new library.
FAQ
What is CVE-2026-111497 (Node2Shell / HTTP2Shell)?
An out-of-bounds write in Google’s Brotli decoder (CWE-787 / CWE-252). Nicknames Node2Shell and HTTP2Shell refer to the same CVE as it showed up first in Node.js write-ups and then across HTTP stacks. The Node.js advisory rates it High and says it permits remote code execution. NVD describes buffer overflow impact including crash, memory disclosure, or potential code execution via a crafted Brotli stream.
Which Node.js versions are fixed?
22.23.4, 24.22.1, and 26.12.1, per the Node.js October 21, 2026 security releases. End-of-life lines are affected with no upstream patch.
Which Bun version is fixed?
1.4.4 or later. See Bun advisory GHSA-663w-cv8g-jj2p. Rebuild bun build --compile executables with that Bun.
Does updating an npm brotli package fix this?
No. The vulnerable decoder is bundled in the Node.js / Bun runtime (and in Envoy’s Brotli decompressor). You must upgrade the runtime or proxy and rebuild anything that embeds it.
Am I safe if I only send Brotli responses?
You are off the highest-priority path if you never decompress untrusted Brotli, but the vulnerable decoder remains in the binary. Patch on the next rebuild. Prioritize any path that accepts br request bodies or fetches br responses from untrusted peers.
What about Envoy and Istio?
Envoy: fixed in 1.40.0, 1.39.3, 1.38.6, 1.37.8, and 1.36.12 (1.36 unsupported). Impact when the Brotli decompressor is configured. Istio: 1.31.2, 1.30.6, 1.29.9 per ISTIO-SECURITY-2026-007; 1.29 is EOL.
Sources
7 refsVersions verified October 26, 2026 (America/New_York) against:
- Node.js, “Wednesday, October 21, 2026 Security Releases”: https://nodejs.org/en/blog/vulnerability/october-2026-security-releasesnodejs.org
- NVD, CVE-2026-111497: https://nvd.nist.gov/vuln/detail/CVE-2026-111497nvd.nist.gov
- CVE record: https://www.cve.org/CVERecord?id=CVE-2026-111497cve.org
- Bun, GHSA-663w-cv8g-jj2p: https://github.com/oven-sh/bun/security/advisories/GHSA-663w-cv8g-jj2pgithub.com
- Envoy, GHSA-3wvj-j6qm-62mr: https://github.com/envoyproxy/envoy/security/advisories/GHSA-3wvj-j6qm-62mrgithub.com
- Istio, ISTIO-SECURITY-2026-007: https://istio.io/latest/news/security/istio-security-2026-007/istio.io
- google/brotli v1.2.1 release: https://github.com/google/brotli/releases/tag/v1.2.1github.com
comments
loading comments…
No comments yet. Start the thread.