Brotli2Shell, CVE-2026-111497 Brotli decoder RCE
CentralCSP Team ·
Last update:
On 21 October 2026, the same day as PHP2Shell, Node.js shipped 22.23.4, 24.22.1 and 26.12.1 to fix CVE-2026-111497, an out-of-bounds write in Google's Brotli decoder. Google rates it 9.2 under CVSS 4.0. The bug is not in Node.js: it is in the C library that decompresses Brotli data, and that library ships inside Node.js, Bun, Python packages, .NET, Envoy, Istio, PHP for Windows and many more. Within a week it collected four nicknames: Node2Shell, HTTP2Shell, Python2Shell and Brotli2Shell.
Researchers have shown remote code execution against official, unmodified Node.js builds. On 26 October, ELLIO reported the first exploit traffic it had seen in the wild.
The short answer, depending on what you run:
- Node.js 22, 24 or 26: update now to 22.23.4, 24.22.1 or 26.12.1.
- Node.js 18, 20, 23 or 25: no fixed release. Move to a supported line.
- Python with
brotliorbrotlicffiinstalled: update tobrotli1.2.1 orbrotlicffi1.2.1.0. - Bun, .NET, Envoy, Istio: update to the fixed versions in the table below.
- Anything else that decompresses Brotli: check whether it links the system
libbrotlior bundles its own copy, and update accordingly.
This post sums up what Brotli2Shell is, who is exposed, how the week unfolded, how to find it in your stack, and what to do now. It stays at the level of what and why: no exploitation details.
What is Brotli2Shell, CVE-2026-111497
Brotli is the compression format Google designed for the web. Browsers announce it in Accept-Encoding: br, and most CDNs and web servers use it to compress pages. CVE-2026-111497 sits in the decoder, the code that turns Brotli data back into the original bytes.
According to the Node.js advisory, an invalid block switch in the compressed stream was reported as "need more input" instead of a format error. The streaming decoder then kept writing input into an eight-byte internal buffer, past its end. Node.js says this can lead to a crash, disclosure of process memory, or remote code execution.
| CVE | CVE-2026-111497 |
| Component | Google Brotli C decoder (c/dec/decode.c), and every product that bundles or links it |
| Type | Out-of-bounds write, from a crash to remote code execution |
| Severity | Critical, 9.2 under CVSS 4.0 as rated by Google. Node.js rates it High, Microsoft rates it 8.1 under CVSS 3.1 for .NET |
| Nicknames | Node2Shell, HTTP2Shell, Python2Shell, Broccoli2Shell, Brotli2Shell. HTTP2Shell has nothing to do with HTTP/2 |
| Reported by | Khai Tran and Sylvie Mayer, OpenAI Codex Security |
| Affected | Brotli 1.0.3 to 1.0.9, 1.1.0 and 1.2.0 |
| Fixed | Brotli 1.0.10, 1.1.1 and 1.2.1 |
The upstream fix is old. Google committed it to the Brotli repository on 27 February 2026 (commit 0ed4268) without a security label, so most downstream projects did not pick it up. That is why the fixed releases arrived product by product over the following week, and why some are still missing.
Who is exposed
A vulnerable decoder only matters when it decompresses data an attacker controls. Many applications do that without ever mentioning Brotli in their code, because HTTP clients and body parsers decompress automatically. JFrog and Phoenix Security group the paths into three families.
Incoming requests. A server that decompresses request bodies sent with Content-Encoding: br. Express 5.0.0 to 5.3.0 and body-parser 2.0.0 to 2.3.0 do this by default (Imperva). ASP.NET Core's request decompression middleware does it when enabled, and Envoy and Istio do it when the Brotli decompressor filter is configured. Imperva notes that a bare Node.js HTTP server does not decode incoming Brotli bodies on its own.
Outgoing requests. A service that fetches a URL and decompresses the response. Node.js and Bun fetch() decode Brotli responses automatically, and so do the Python clients urllib3, requests, httpx and aiohttp when the brotli or brotlicffi package is installed, including through extras such as urllib3[brotli]. Phoenix Security lists webhooks, link previews, crawlers and AI browsing agents as the typical targets: anything that fetches a URL a user can choose.
Files. Brotli also hides inside file formats: Parquet pages, JPEG XL images, WOFF2 fonts, some PDFs and archives. JFrog reached the decoder through FFmpeg with a JPEG XL file, Apache Arrow with a Parquet file, and crashed ClickHouse with a single compressed request.
Some common stacks are out of the inbound path by default. .NET leaves Brotli decompression off unless the application opts in, and .NET Framework is not affected. Phoenix Security notes that nginx and Apache compress responses with Brotli but do not decode Brotli request bodies by default, and compression uses the encoder, not the decoder.
How the week unfolded
- 27 February. Google commits the fix upstream, with no advisory.
- Early October. Envoy and Istio ship fixed releases without naming the flaw (Tenable).
- 21 October. Node.js publishes its October security releases with the Brotli fix and nine other CVEs. Google tags Brotli 1.0.10, 1.1.1 and 1.2.1. Vercel deploys WAF rules for inbound requests (Vercel).
- 22 October. NVD publishes the CVE record and Brotli 1.2.1 reaches PyPI. Imperva publishes its research under the name Node2Shell: it ran code on the official Node.js 24.22.0 Linux arm64 build, and has not released the exploit.
- 23 October.
brotlicffi1.2.1.0 ships, the name HTTP2Shell appears, and CISA's assessment lists exploitation as "none" and technical impact as "total" (Phoenix Security). - 25 October. Microsoft releases out-of-band .NET updates (dotnet/announcements#494) and Cloudflare ships an emergency WAF release for inbound request bodies.
- 26 October. PHP publishes new Windows builds bundling Brotli 1.2.1, five days after its own PHP2Shell release. ELLIO reports exploit traffic in the wild: a single 23 MB request body built for Node.js 24.22.0 on x86-64, which copies the public proofs of concept. ELLIO also says it reproduced code execution on official x86-64 builds, including Express 5.3.0 and Koa 3 applications, with default settings.
As of 26 October, Tenable had not independently confirmed the exploitation ELLIO reported, and CVE-2026-111497 was not in CISA's Known Exploited Vulnerabilities catalog. Wiz says 91% of the cloud environments it sees have resources vulnerable to CVE-2026-111497.
Which versions are affected and fixed
| Product | Affected | Fixed in |
|---|---|---|
| Google Brotli (C library) | 1.0.3 to 1.0.9, 1.1.0, 1.2.0 | 1.0.10, 1.1.1, 1.2.1 |
| Node.js 22, 24, 26 | Below 22.23.4, 24.22.1, 26.12.1 | 22.23.4, 24.22.1, 26.12.1 |
| Node.js 18, 20, 23, 25 | All | No release, end of life |
| Bun | 1.0.21 to 1.4.3 | 1.4.4 |
Python brotli | 1.0.3 to 1.2.0 | 1.2.1 |
Python brotlicffi | 1.0.3 to 1.2.0.x | 1.2.1.0 |
| .NET 8, 9, 10 | Below 8.0.33, 9.0.22, 10.0.14 | 8.0.33, 9.0.22, 10.0.14 |
| Envoy | Up to 1.36.11, 1.37.7, 1.38.5, 1.39.2 | 1.36.12, 1.37.8, 1.38.6, 1.39.3, 1.40.0 |
| Istio | Below 1.29.9, 1.30.6, 1.31.2 | 1.29.9, 1.30.6, 1.31.2 |
| PHP for Windows | Builds bundling Brotli 1.0.3 to 1.2.0 | 8.2.35-1, 8.3.36-1, 8.4.27-1, 8.5.12-1 |
PHP brotli extension | Below 0.21.1 | 0.21.1 |
Java brotli4j | Below 1.24.0 | 1.24.0 |
Go andybalholm/brotli | Below 1.2.7 | 1.2.7, crash only |
Sources: Tenable, Wiz and Phoenix Security. The Broccoli2Shell tracker lists Chromium, Firefox and the nginx module ngx_brotli as fixed before it started. Keep browsers on their latest release as usual.
Bundled copies, where updating Brotli is not enough
Brotli is small, so many projects copy its source into their own build instead of linking the system library. Updating your distribution's libbrotli fixes programs that link it, once they restart. It does nothing for a copy compiled into another binary or a Python wheel.
As of 26 October, Phoenix Security listed these as still unfixed: Pillow, pyarrow, curl-cffi and pycurl wheels, DuckDB, ClickHouse, Apache Arrow bundled builds, libjxl, 7-Zip-zstd, p7zip, NanaZip and Git for Windows. JFrog warns that "the upstream version number alone is not always sufficient": a vendor can backport the fix without changing the Brotli version string, and a bundled copy can be vulnerable while the system library is patched.
Am I using it? Check if a website runs Node.js
Node.js is the most exposed runtime, because it bundles the decoder, decodes fetch() responses by default, and powers Express, the most common body parser. Most Node.js on the web arrives through a framework: Express, Next.js, Nuxt, NestJS, Koa, Fastify, Remix, Astro or SvelteKit in server mode.
To check one site from the outside, paste its URL into the free Technology Checker. It reports Node.js when the server reveals it, and the frameworks that imply it, such as Express or Next.js. The classic tell is an X-Powered-By: Express header, which is also an information leak worth removing.
An outside scan shows what serves your pages. It cannot see the outgoing path: the worker that fetches webhooks, the crawler, the Python script that calls a partner API. Those need a check from the inside:
node -v # Node.js runtime
bun --version # Bun runtime
pip show brotli brotlicffi # Python packages
dotnet --list-runtimes # .NET runtimes
dpkg -l 'libbrotli*' # Debian and Ubuntu system library
rpm -qa 'brotli*' # Red Hat, Rocky, Alma system libraryRun them inside each container image, not only on the host: a container carries its own Node.js and its own Python packages. JFrog publishes an open-source scanner that looks for Brotli decompression paths in JavaScript, Python and ELF binaries. A match shows where to look, not that the path is reachable.
Am I vulnerable to Brotli2Shell?
Two questions decide it: does the component run an affected decoder, and can an attacker reach it with Brotli data?
- List every runtime and service that can decode Brotli. Node.js, Bun, Python environments with
brotliorbrotlicffi, .NET with Brotli decompression enabled, Envoy and Istio with the Brotli decompressor, and any tool from the bundled copies list above. - Read the version in each environment with the commands above, and compare it with the table.
- Find the input paths. A public endpoint that parses request bodies, a service that fetches URLs chosen by users, or a pipeline that processes uploaded files. Prioritise anything reachable from the internet.
A version outside the affected range rules the CVE out for that component. A version inside it, with an input path an attacker controls, means the service is exposed until it is patched.
What to do now
Our recommendations, from the most urgent:
- Patch Node.js and Bun now. Update to Node.js 22.23.4, 24.22.1 or 26.12.1, or Bun 1.4.4. Rebuild container images on a patched base and redeploy them, and restart long-running processes: the old decoder stays in memory until the process exits. Move servers on Node.js 18, 20, 23 or 25 to a supported line.
- Update the other runtimes and libraries. Python
brotli1.2.1 orbrotlicffi1.2.1.0, .NET 8.0.33, 9.0.22 or 10.0.14, Envoy and Istio to the fixed releases, PHP for Windows to the 26 October builds. Then update the systemlibbrotliand restart what links it. - Block Brotli request bodies where you cannot patch today. Reject requests with
Content-Encoding: brat the load balancer or reverse proxy, and disable the Brotli decompressor in Envoy and Istio. Cloudflare, Vercel, Imperva and Azure have deployed WAF rules, but those rules cover request bodies only (Tenable). - Cut the outgoing path too. A WAF does not see the responses your services fetch. Disable Brotli decoding in your HTTP clients, or uninstall the Python
brotliandbrotlicffipackages until the patched versions are in place. Tenable notes that removingbrfromAccept-Encodingis not enough, because a malicious server can send Brotli anyway. - Watch for crashes and unusual behaviour. A failed attempt often crashes the process, so a spike of Node.js or Python worker restarts is a signal. Look for unexpected child processes spawned by the service user, outbound connections from web workers, and very large compressed request bodies. ELLIO published an indicator of compromise in its report.
Keep an inventory before the next one
Brotli2Shell is the third time this year the first question was "where do we run it?". It was Next.js in August and PHP last week. This time the answer is harder, because the vulnerable code is a library inside runtimes and packages, not a product you chose.
For server-side software, the free Technology Checker is the quick outside view, and the commands above cover the inside. For the code that runs in your visitors' browsers, CentralCSP keeps the inventory current: it lists the scripts each page loads, identifies the library and version behind each one, and alerts you when a new CVE affects a version you serve. The inventory is described in Technologies, and the supply-chain feature page has the tour. Start free with CentralCSP to see your own sites.
FAQ
What is Brotli2Shell?
Brotli2Shell is one of the nicknames for CVE-2026-111497, an out-of-bounds write in Google's Brotli decoder, disclosed on 21 October 2026. Node2Shell, HTTP2Shell, Python2Shell and Broccoli2Shell are the same vulnerability.
Are Node2Shell and HTTP2Shell different vulnerabilities?
No. Both names refer to CVE-2026-111497. Node2Shell came from the first demonstration against Node.js, and HTTP2Shell from its reach across HTTP stacks. HTTP2Shell is not related to the HTTP/2 protocol.
Which Node.js versions fix CVE-2026-111497?
Node.js 22.23.4, 24.22.1 and 26.12.1. Node.js 18, 20, 23 and 25 are end of life and get no fix.
Is my Express application vulnerable?
Express 5.0.0 to 5.3.0 decodes Brotli request bodies by default, so an Express 5 application on an unpatched Node.js is exposed to incoming requests. The fix is in Node.js, not Express: update Node.js.
Is a site that serves Brotli-compressed pages vulnerable?
Serving Brotli uses the encoder, and the flaw is in the decoder. A server is exposed when it decompresses Brotli data it receives, in request bodies, fetched responses or files.
Are browsers affected?
Browsers decode Brotli on every page load. The Broccoli2Shell tracker lists Chromium and Firefox as fixed before it started, without versions. Keep browsers updated as usual.
Is Brotli2Shell being exploited in the wild?
On 26 October, ELLIO reported exploit traffic targeting Node.js 24.22.0 on x86-64. Tenable had not independently confirmed it, and the CVE was not in CISA's KEV catalog that day. Imperva and ELLIO have both shown code execution on official Node.js builds. Treat any unpatched service that decodes untrusted Brotli data as a target.
Is my site safe if it is behind Cloudflare?
Only for incoming requests. Cloudflare's WAF rules inspect request bodies, so they do not protect a service that fetches a malicious Brotli response from another server. An attacker who reaches your origin directly also bypasses them. Patch anyway.
Related
- PHP2Shell, CVE-2026-109618 and CVE-2026-109619 PHP RCE
- Next.js vulnerabilities in 2026, the AVIF RCE and the version to run
- What technology is this website using, and is any of it outdated
- How to detect vulnerable JavaScript libraries on a live website
Sources
- Node.js, October 2026 security releases
- Google Brotli, commit 0ed4268
- Tenable, Brotli2Shell FAQ
- JFrog Security Research, Brotli2Shell: beyond Node2Shell and HTTP2Shell
- Imperva, Node2Shell: from Brotli data to remote code execution
- ELLIO, Node2Shell RCE on stock Node.js builds
- Wiz, Broccoli2Shell: the critical Brotli decoder vulnerability
- Phoenix Security, HTTP2Shell, from Node2Shell to every HTTP stack
- Broccoli2Shell tracker
- Vercel, Node.js security advisory
- Microsoft, .NET security updates
- PHP, Windows builds with Brotli 1.2.1
- JFrog, Brotli2Shell scanner