Brotli RCE CVE-2026-111497: 25 of 37 Node runtimes below the fixed version
On 21 October the Node.js project released three maintenance versions that, among other things, fix a write error in the bundled Brotli decoder. The decoder comes from Google and sits inside many other products. On the morning of 26 October we read out 37 Node runtimes on four of our hosts: 12 run a patched version and 25 run something older. A second finding concerns how you can tell a patch level at all.
CVE-2026-111497 in short: a crafted Brotli stream makes the decoder write past the end of an eight-byte internal buffer. That can crash the process, leak memory or run code. The affected component is Google's decoder in versions 1.0.3 through 1.2.0, so any software that feeds it untrusted data is exposed: Node.js, the PyPI packages Brotli and brotlicffi, .NET and more. The fixed versions 1.0.10, 1.1.1 and 1.2.1 have been out since 21 October 2026.
Status on 5 November: the flaw is being exploited
This post first appeared on 26 October. Rechecking it on 5 November, three statements needed correcting.
First, exploitation. The original text said the CISA list did not contain this CVE. That was true on the day we looked. Since 27 October 2026 it is listed, with a deadline of 10 November for US federal agencies. We read it again on 5 November in the CISA catalog (catalog version 2026.11.04, 1,768 entries). CISA marks ransomware use as "Unknown".
Second, exploit reach. We had written that the public proof of concept only crashes standard builds. That was the claim of a community overview. ELLIO says instead that it got a shell with this exploit on unmodified x86-64 builds, against four targets, and that its sensors saw exploit traffic with the same code on 26 October. Anyone patching should assume code execution.
Third, the NVD entry. On 26 October it read "Awaiting Analysis". Today it reads "Analyzed" and carries an additional NIST CVSS 3.1 score of 9.8.
We updated our own hosts on 27 October. Our own images and host Node have run 24.22.1 since that evening, and a drift check over 49 hosts reported no finding. That comes from an internal operations note and cannot be verified publicly. The measurements below are the state of 26 October, before those changes.
What the flaw does and what it needs
The decoder switches between block types while unpacking. Before the fix, the responsible function reported an invalid block switch as "need more input" instead of a permanent format error. The streaming decoder therefore kept appending attacker bytes to an eight-byte buffer and wrote beyond its end. That is how the Node.js advisory describes it. Node.js ships the upstream fix as a cherry-pick in 22.23.4, 24.22.1 and 26.12.1. The project also notes that end-of-life versions are always affected by a security release. According to broccoli2shell.com they get no fix and have to move to 22, 24 or 26.
What matters is where the decoder touches untrusted data. The overview at broccoli2shell.com, an independently run community page, lists three routes. Node's built-in fetch() decodes responses with Content-Encoding: br by itself. Express 5.0.0 through 5.3.0 and body-parser 2.0.0 through 2.3.0 decode Brotli request bodies. A direct zlib.brotliDecompress() call handles archives or queue messages. A bare node:http server does not decode incoming bodies on its own, which Imperva confirms. Imperva ran code on the official Node.js 24.22.0 image (Linux arm64), through a fetched response and through an Express request body, after several attempts. 24.22.1 rejected the same inputs. That Imperva has not released the exploit is stated by broccoli2shell.com; the Imperva page says nothing on it.
According to broccoli2shell.com, on Python it is enough that the package Brotli or brotlicffi is installed. urllib3, requests and aiohttp negotiate Accept-Encoding: br and call the decoder without any of your own code naming it. OpenSourceMalware showed in a sanitizer test that Brotli 1.2.0 lets a crafted stream of about 23 MB through and 1.2.1 rejects it with format error -17. Nobody there tried an exploit for Python. Official Node.js builds and images bundle their own copy, so the system libbrotli1 does not help there. According to ELLIO and the Debian tracker ("nodejs uses system provided brotli library"), distribution packages of Node link the system library instead, and for those its package version decides.
According to broccoli2shell.com the product list runs from Bun and Envoy through Ruby bindings to .NET. Istio does not appear there; the Istio versions are listed by Wiz. Microsoft lists the .NET side in its Security Response Center entry as a privilege escalation reachable over the network, rated Critical and published on 25 October. According to the same page, bundled copies were still waiting for their maintainers on 28 October, among them DuckDB, Apache Arrow, p7zip and the UEFI firmware EDK II. We have not checked whether they are patched by now.
Who rates it how
Severity depends on who counts. We read the values below from the sources on 5 November. The unit is the respective CVSS score.
| Source | Rating | Scale |
|---|---|---|
| Node.js advisory | high | the project's own rating |
| GitHub Advisory Database | Critical, 9.2 | CVSS 4.0 |
| NVD, submitted by Google | Critical, 9.2 | CVSS 4.0 |
| NVD, NIST | Critical, 9.8 | CVSS 3.1 |
| Microsoft (.NET) | Critical, base score 8.1 | elevation of privilege |
The 9.2 vector assumes full loss of confidentiality, integrity and availability on the attacked system, with no consequences for other systems. The Node project stays below that with "high". Wiz reports from its own telemetry that 91 percent of cloud environments have affected resources. That is a figure from a security vendor with its own interest in the finding, and we cannot verify it.
Disclosure timeline
All dates come from the linked sources. We measured none of them ourselves.
| Date | Event | Source |
|---|---|---|
| 21 Oct | Node.js 22.23.4, 24.22.1, 26.12.1 and Brotli 1.0.10, 1.1.1, 1.2.1 released | Node.js, Google |
| 22 Oct | NVD entry, GitHub advisory, PyPI package Brotli 1.2.1, Imperva report, public proof of concept | NVD, GitHub, OpenSourceMalware, Imperva, broccoli2shell.com (proof of concept) |
| 23 Oct | brotlicffi 1.2.1.0 on PyPI | OpenSourceMalware |
| 25 Oct | .NET updates and MSRC entry | Microsoft |
| 26 Oct | ELLIO reports exploit traffic with the public exploit | ELLIO |
| 27 Oct | Added to the CISA catalog, deadline 10 Nov | CISA |
What we measured
On 26 October between 07:24 and 07:31 UTC we queried, over SSH, every Node host and every Node container on four hosts (.181.3, .200.11, .180.2 and .180.1). The unit is the Node release number from node --version, compared against the fixed versions 22.23.4, 24.22.1 and 26.12.1.
| Measuring point (own measurement, 26 Oct 2026) | Runtimes | Node version | Status |
|---|---|---|---|
| Blog host .181.3, host plus three Next.js containers | 4 | 24.22.1 | at the fixed version |
| Umami container on .181.3 | 1 | 22.23.4 | at the fixed version |
| tl-gui and zahlungen-ui on .200.11 | 2 | 24.22.1, 22.23.4 | at the fixed version |
| agent-watchdog, rbs-kompensator, rbs-kalkulator-mcp, zahlungen-ui (.180.2) | 4 | 22.23.4 | at the fixed version |
| dsh-eval on .180.1 | 1 | 22.23.4 | at the fixed version |
| slg-tickets, slg-pruefungen, senn-frachttarife, mcp-erp-lookup (.200.11) | 4 | 24.22.0 | one patch below |
| litellm-router on .200.11 | 1 | 26.12.0 | one patch below |
| Host .200.11 | 1 | 22.22.1 | below |
| open-design, mcp-open-design, librechat-api (.180.2) | 3 | 24.21.0 | below |
| litellm-router container on .180.2 | 1 | 26.10.0 | below |
| 11 MCP and KSA containers (.180.2), including mcp-erp-lookup and senn-agent-mcp | 11 | 22.22.2 to 22.23.3 | below |
| Host .180.2 | 1 | 22.22.1 | below |
| Crawl host .180.1 | 1 | 22.22.1 | below |
| senn-tech-preview and dsh-capacity-sidecar (.180.1) | 2 | 22.23.3 | below |
The runtimes add up to 12 at the fixed version and 25 below, 37 in total. "Below" only says the release number is under the fix. How dangerous that is depends on the path. LibreChat and Open Design fetch responses from external AI providers and web services and so hit the outbound decoding path, because any server they talk to may answer with Content-Encoding: br. The four SLG containers on .200.11 talk internally to OSRM, ERP and the database, so their data source is normally in-house.
Three paths were closed on the same morning: Zammad 7.2 does not know the Ruby Brotli gem, the PHP Brotli extension is not loaded on our web host, and in the LiteLLM container import brotli fails because the package is missing. We could not measure the Windows fleet, the dc1 host without a key, or the backup host, which refused SSH.
The version shown in the binary is not the patch
On the crawl host .180.1, v22.22.1 ran on 26 October. The system package libbrotli1 stood at 1.2.0-3build1, also inside the affected range, and our package sources offered nothing newer that day. That is a snapshot of 26 October; distribution packages catch up, so a later query can look different.
When you check a patch level, the decoder version display misleads. Node.js applied the fix as a single upstream commit, and the release notes for Node.js 24.22.1 list it as deps: brotli: cherry-pick 0ed4268a…. The bundled number in process.versions.brotli did not follow reliably. A remeasurement on 5 November gave:
| Host (own measurement, 5 Nov 2026) | node --version | process.versions.brotli |
|---|---|---|
| Blog host .181.3 | v24.22.1 | 1.2.1 |
| dsh host .180.1 | v24.22.1 | 1.2.0 |
The same release therefore reports two different decoder numbers. A check script that demands "brotli 1.2.1 or higher" rates two equally patched binaries differently. We do not know why the numbers diverge, and the sources do not explain it. With automated scanners, check Node's release number against the advisory, add pip show Brotli brotlicffi for Python, and read the package state with dpkg, rpm or apk for system libraries.
What companies should do now
Start with the inventory. Node programs run in companies that never ordered them: behind Next.js front ends, n8n, Node-RED, chat interfaces and monitoring appliances there is a Node runtime, and the release number decides the state, not the install date. That includes laptops with browsers, NAS interfaces and tools with a bundled copy such as p7zip. For a flaw that CISA lists as exploited, services that fetch foreign URLs or accept br request bodies come first.
The rebuild is what works. A host update does not reach images. Containers need a patched base and a new build, Python lockfiles need updated entries, or the next run brings the old version back. If you cannot switch at once, broccoli2shell.com advises rejecting Content-Encoding: br at the proxy or gateway and uninstalling Brotli and brotlicffi on Python, so that urllib3 and requests fall back to gzip. For outbound requests this helps only partly, since a server may send Brotli unasked. According to broccoli2shell.com, the Node project has published no workaround.
If you would rather not take the inventory yourself, you can commission it through our IT service for infrastructure and operations. How such a fleet check runs step by step across hosts, containers and package states is written up in the curl fleet check, and the same order stands behind this post. The post on the Brotli flaw in Node.js, Python and .NET summarises the disclosure and the .NET and Python fixes; this post instead rests on the measurement of our own fleet and tracks the exploitation status. Other flaws where we remeasured our estate are collected in the Security and privacy topic hub, for instance the PHP RCE patch day with the same restart trap.
Further sources
- Node.js project: Wednesday, October 21, 2026 Security Releases, 21 Oct 2026
- Node.js project: Node.js 24.22.1 (LTS), 21 Oct 2026
- Google: Brotli releases 1.0.10, 1.1.1, 1.2.1, 21 Oct 2026
- GitHub Advisory Database: GHSA-9v8h-qqgm-4m35, as of 3 Nov 2026
- NVD: CVE-2026-111497, retrieved 5 Nov 2026 via the NVD API (status Analyzed)
- CISA: Known Exploited Vulnerabilities Catalog and catalog as JSON, as of 4 Nov 2026
- Microsoft: CVE-2026-111497 in the Security Update Guide, 25 Oct 2026
- Imperva: Node2Shell: From Brotli Data to Remote Code Execution, 22 Oct 2026
- ELLIO: Node2Shell: remote code execution on stock Node.js builds, 25 Oct 2026, update 26 Oct 2026
- OpenSourceMalware: Impact of the Brotli flaw on Python packages, 23 Oct 2026
- Wiz: Broccoli2shell overview, 25 Oct 2026
- Community overview: broccoli2shell.com, independently maintained, as of 28 Oct 2026
Is CVE-2026-111497 being exploited?+
Yes. CISA added the flaw to its Known Exploited Vulnerabilities catalog on 27 October 2026, with a deadline of 10 November for US federal agencies. The security firm ELLIO reported exploit traffic carrying the public exploit as early as 26 October. The first version of this post, written on 26 October, said the opposite, because the catalog entry came a day later.
Is apt upgrade on the host enough?+
Not for every Node program. Official Node.js builds and images bundle their own copy of the decoder, so the system libbrotli1 changes nothing there. According to ELLIO and the Debian tracker, distribution packages of Node link the system library instead, and for those the libbrotli1 package matters too. Containers run a filesystem from their image, which no host update reaches. The step that works is rebuilding the image on a patched base and restarting the process, because a running process keeps the old decoder.
Why does my patched Node 24.22.1 still report Brotli 1.2.0?+
The Node project applied the fix as a single upstream commit (a cherry-pick, per the 24.22.1 release notes) and, according to ELLIO, did not raise the bundled version number. On 5 November the same release 24.22.1 showed 1.2.0 on one of our hosts and 1.2.1 on another. Compare Node's release number with the advisory list. The decoder version is not reliable proof of a patch.
senn-tech