HTTP2Shell: The Brotli Bug Behind Node2Shell Hits Python, Bun, Envoy and More
Node2Shell was never just a Node.js bug. The same Brotli flaw reaches Python, Bun, Envoy, Istio, curl and bundled copies everywhere. Here’s how to check and fix.

HTTP2Shell is the name researchers now use for CVE-2026-111497, a memory-corruption bug in Google's Brotli decoder. Brotli is the compression behind the br in Content-Encoding: br. Its C decoder is copied into language runtimes, Python packages, proxies, command-line tools, databases and archive tools. So HTTP2Shell isn't one product's bug. It's a shared-library bug that every one of those projects has to fix separately.
If you run Python services, use Bun, run Envoy with Brotli decompression, rely on curl, or use tools that ship their own copy of Brotli, this may reach you even if your own code never mentions compression. This guide covers what HTTP2Shell is, which software is affected (and which isn't), how to check your systems, and what to do if you can't patch today.
The short version
The bug: an out-of-bounds write in Google's Brotli C decoder, versions 1.0.3 through 1.2.0. Crafted compressed data can crash a program, leak memory, or in the worst case run attacker-controlled code.
The fix upstream: Brotli 1.0.10, 1.1.1 and 1.2.1. Every project that bundles the decoder must ship its own update.
Python surprise: if the
Brotliorbrotlicffipackage is installed,requests,urllib3,aiohttpandhttpx(with its brotli extra) decode Brotli automatically, even if your code never imports it.Exploitation: no attacks in the wild reported as of October 24, 2026, and not in CISA's KEV catalog. Code execution has been shown in a lab on one runtime build.
After updating, restart. A running process keeps the old decoder in memory.
What is HTTP2Shell?
HTTP2Shell is a bug in the C code that unpacks Brotli data, not the code that compresses it. Any program that decompresses Brotli data someone else controls can be affected. That includes request bodies sent to a server, responses a client downloads, and files opened from outside sources.
The name comes from how far the bug reaches over ordinary HTTP traffic: HTTP clients and servers decode Content-Encoding: br automatically, often without the developer ever choosing to.
Severity ratings vary by who is scoring it:
Google, which assigned the CVE: 9.2 Critical (CVSS 4.0)
GitHub advisory GHSA-9v8h-qqgm-4m35: Critical, 9.2 (CVSS 4.0)
Red Hat: 8.1 Important
Node.js: High, for its own runtime
Which software is affected by HTTP2Shell?

One C library, many copies: where the HTTP2Shell decoder lives, and fix status as of October 24, 2026.
Anything that ships, bundles or links Brotli 1.0.3 through 1.2.0 and decodes data it doesn't control. Here's the status as of October 24, 2026.
Fixed releases available
Google Brotli (C library): affected 1.0.3–1.2.0 → fixed in 1.0.10, 1.1.1, 1.2.1. Exposed when code decodes untrusted Brotli.
Python
Brotli(PyPI): affected 1.2.0 and earlier → fixed in 1.2.1. Exposed when installed and an HTTP client decodesbr.Python
brotlicffi(PyPI): affected 1.2.0.x and earlier → fixed in 1.2.1.0. Same exposure.Bun: affected 1.4.3 and earlier → fixed in 1.4.4. Exposed via
fetch()of abrresponse ornode:zlib.Node.js: fixed in 22.23.4, 24.22.1, 26.12.1. Versions 20, 23 and 25 are end of life and get no fix. (Full Node.js details are in our Node2Shell guide.)
Envoy: Envoy's advisory (GHSA-3wvj-j6qm-62mr, October 23) lists 1.39.2, 1.38.5, 1.37.7 and 1.36.11 as affected, with fixes in 1.40.0, 1.39.3, 1.38.6, 1.37.8 and 1.36.12. Exposed only if a Brotli decompressor is configured in the filter chain.
cdxgen: standalone binaries and images 13.4.0 and 12.8.8 and earlier → fixed in 13.5.0 and 12.8.9.
Linux distribution packages
System libbrotli packages are being fixed on each distribution's own schedule. Debian accepted security updates on October 23 for Debian 12 (1.0.9-2+deb12u1) and Debian 13 (1.1.0-2+deb13u1). Debian unstable still showed 1.2.0-4 with no fix upload as of October 24. Amazon Linux 2023 listed its brotli and Node.js 24 packages as pending as of October 22. Check your distribution's security tracker for your exact release.
Software that bundles its own copy
Updating the system library does not fix software that carries a private copy of the decoder. According to a public tracker run by independent researchers (as cited by Strobes on October 24), these were still awaiting fixes, with several in progress:
The .NET runtime (
BrotliDecoder,BrotliStreamandHttpClientautomatic decompression)The PHP brotli extension and the Ruby brotli gem
DuckDB, ClickHouse, YDB and Apache Arrow's bundled build
libjxl, MuPDF, NanaZip, 7-Zip-zstd and p7zip
EDK II and UEFITool
The same tracker reported that Chromium, Firefox, ngx_brotli, Brotli4j and Ghostscript had already shipped updates. This list changes daily, so confirm with each vendor's own advisory.
What about Istio?
Istio's data plane is built on Envoy. As of October 24, Istio's official security bulletins page had no bulletin mentioning Brotli or CVE-2026-111497. Some coverage has listed Istio "fixed" versions, but we couldn't match those to any Istio advisory, so we're not repeating them. If you've enabled Brotli decompression through an EnvoyFilter, watch Istio's bulletins for an Envoy update.
What is not affected?
Pure reimplementations: the Java, JavaScript and C# ports of Brotli can't reach the bug. Rust's
brotli-decompressorcatches the bad state and returns an error. The Go port (andybalholm/brotli) had the same logic mistake but could only crash, and was fixed on October 23.Default Apache and Nginx: they don't decode Brotli request bodies by default. Compressing responses uses the encoder, not the decoder.
Envoy without a Brotli decompressor configured: the vulnerable code isn't reached.
Servers that never decode request bodies: receiving Brotli data isn't enough. Something has to decompress it.
How does the Brotli decoder bug work?
You don't need to read C to follow this.
A Brotli stream is split into blocks, and the decoder switches between block types as it reads. A function called DecodeBlockTypeAndLength() handles those switches. In vulnerable versions it could only answer "yes" or "no," and a "no" could mean either "this stream is broken" or "I need more data." The calling code couldn't tell them apart, and on the decoder's fast path the answer was ignored entirely.
An attacker can build a stream that announces one block type and then forces a switch that can never succeed. The vulnerable decoder treats that as "wait for more data." According to the Node.js advisory, the streaming decoder then keeps appending attacker-supplied bytes to an eight-byte internal buffer and writes past its end, corrupting nearby memory.
The CVE lists two weaknesses: CWE-252 (unchecked return value) and CWE-787 (out-of-bounds write). Google's fix, commit 0ed4268, makes the function return a real error code and adds a new one, BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH (value -17), so decoding stops on both paths.
Why did the fix take eight months to ship?
The fix was added to Brotli's source code on February 27, 2026, but no Brotli release included it until October 21. OpenAI's Codex Security team, which reported the flaw, said the root cause "was actually fixed in the Brotli source code in February, but it wasn't known at the time that it gave rise to a security vulnerability and there was no more recent release of Brotli." Strobes summarised the result: nobody connected the change to remote code execution until October, which is why downstream projects never pulled it in.
Who is actually exposed to HTTP2Shell?
A vulnerable version alone isn't enough. You're exposed when attacker-controlled Brotli data reaches the decoder, which happens in three ways.
1. Outbound: responses your code downloads
This is the path most teams will miss, and web application firewalls can't see it, because the data comes back from a server your code called.
Python: with
Brotliorbrotlicffiinstalled,urllib3(and thereforerequests) andaiohttpdecode Brotli responses automatically.httpxdoes when itsbrotliextra is installed. Scrapy and anything built on these clients inherit the behaviour. No import is needed in your own code.curl: on Debian 12 and Ubuntu 24.04, libcurl links the system libbrotli, so
curl --compressedand apps that enable libcurl's automatic decoding depend on your distribution's fix.JavaScript runtimes: Bun's and Node.js's built-in
fetch()decode Brotli responses automatically.
OpenAI's disclosure describes the bug as working in both directions: a malicious client can attack an unpatched server, and "an unpatched client that accepts compressed input (such as curl --compressed) could be taken over by a malicious server."
Any feature that fetches a URL an outsider chooses is a delivery channel. That includes webhook deliveries, link previews, "import from URL" features, crawlers, image proxies, OAuth and OIDC discovery, and AI agents that browse the web.
2. Inbound: request bodies your server decompresses
Servers are exposed when middleware inflates br request bodies. Python frameworks and middleware that do this are in scope, as is Envoy with a Brotli decompressor in the filter chain. On the JavaScript side, Express 5's default JSON parser decodes Brotli bodies. Our Node2Shell guide covers that case in detail.
3. Direct: data your code decompresses
Code that calls Python's brotli.decompress(), Node's zlib.brotliDecompress() or similar on untrusted input is exposed. So are tools that open Brotli-compressed Parquet files, JPEG XL images, PDFs, archives, caches or queue messages from outside sources. It's the same "native decoder meets untrusted file" pattern as the Pillow image bugs this week.
Is HTTP2Shell being exploited in the wild?
Not as far as anyone has confirmed. Here's where things stood on October 24:
Out-of-bounds write: confirmed by the Node.js advisory, the CVE record and Brotli's changelog.
Code execution: Imperva's Red Team ran attacker-supplied code on an unmodified Node.js 24.22.0 build for Linux arm64. It took several attempts, wasn't released, and wasn't tested on other builds. It hasn't been demonstrated on Python, Bun or Envoy.
Python packages: memory corruption confirmed with AddressSanitizer by OpenSourceMalware's analysis; no exploit attempted.
Public proof-of-concept code: on GitHub since October 21–22. Red Hat says there is no reliable public proof-of-concept for running code.
CISA KEV: not listed. CISA's October 23 assessment recorded exploitation as "none."
Attacks in the wild: none reported.
A KEV listing requires evidence of real-world exploitation (our CISA KEV explainer covers how the catalog works). A missing entry means no attacks have been confirmed yet, not that the bug is low risk. Also be wary of "free HTTP2Shell scanners" and exploit repositories using these names. Run anything like that only in an isolated lab.
How do I check if I'm vulnerable to HTTP2Shell?
Don't send exploit traffic at production. Check versions and code paths instead, everywhere code runs: production, staging, CI runners, build images, serverless functions and developer laptops.
Step 1: Find every copy of the decoder
# System libbrotli version
dpkg -l | grep -i brotli # Debian, Ubuntu
rpm -qa | grep -i brotli # RHEL, Fedora
apk info -v | grep -i brotli # Alpine
# Running processes that have the system decoder loaded right now
sudo grep -l brotlidec /proc/*/maps 2>/dev/null
# Does your curl use Brotli? (look for "brotli" under Features)
curl -VThe /proc check only finds processes using the shared system library. Programs with a bundled copy, such as Node.js, Bun and many vendor tools, won't show up there, so check them by version.
Step 2: Python
# Installed, and which version? (need Brotli 1.2.1+ / brotlicffi 1.2.1.0+)
pip show Brotli brotlicffi
# What pulled it in?
pipdeptree -r -p Brotli
# Lock files
grep -i brotli poetry.lock uv.lock requirements*.txt Pipfile.lock 2>/dev/nullDon't rely only on your dependency scanner here. Aikido reported on October 23 that pip-audit, Dependabot and Safety weren't flagging these versions, because advisory databases hadn't mapped the CVE to the PyPI packages. GitHub's advisory (GHSA-9v8h-qqgm-4m35) names Google's Brotli project but had no affected package attached when we checked. Python advisory entries PYSEC-2026-4322 and PYSEC-2026-4323 were added on October 23. Check installed versions by hand.
Step 3: JavaScript runtimes
# Bun (affected if 1.4.3 or earlier)
bun --version
# Node.js (need 22.23.4+, 24.22.1+ or 26.12.1+), and its bundled Brotli version
node --version
node -p "process.versions.brotli"Step 4: Proxies and containers
# Envoy version, then look for a Brotli decompressor in your config
envoy --version
grep -ri brotli /path/to/envoy/config
# Inside a container image
docker run --rm --entrypoint pip <image> show Brotli brotlicffiHow do I fix HTTP2Shell?
Update every copy to a fixed version: the system libbrotli through your distribution, Python
Brotli1.2.1 andbrotlicffi1.2.1.0, Bun 1.4.4, Node.js 22.23.4 / 24.22.1 / 26.12.1, Envoy 1.40.0 or the fixed release on your branch, and cdxgen 13.5.0 / 12.8.9.Restart every process. A running program keeps the old decoder in memory until it restarts.
Rebuild and redeploy images on patched bases, then confirm the version inside the running container. A Dockerfile pinned to an old tag stays vulnerable however often you rebuild it. Our Docker rollout checklist applies here too.
Update lock files. Raise the constraint and regenerate
poetry.lock,uv.lockorrequirements.txt, or the next build quietly reinstalls the vulnerable version.Ask your vendors. Appliances, agents, SDKs and desktop tools that bundle Brotli need their own updates. Ask: "Do you ship Brotli 1.0.3 to 1.2.0, and when will you update?"
What can I do if I can't patch HTTP2Shell today?
These are bridges to the update, not replacements for it.
Python: uninstall Brotli where it's optional.
pip uninstall -y Brotli brotlicffi, and remove extras such ashttpx[brotli]so the next install doesn't bring them back.urllib3,requestsandaiohttpfall back to gzip and deflate. Strobes notes this is the only stopgap that covers both inbound and outbound paths. Aikido warns that servers which still send Brotli may then return unreadable responses.Reject
Content-Encoding: brrequest bodies at your proxy, load balancer or middleware, before anything decodes them. Aikido recommends matching case-insensitively, including inside lists. Vercel and Imperva added WAF rules for this on disclosure day. This covers inbound traffic only.Reject Brotli responses before decoding in HTTP clients you control, and turn off automatic Brotli decoding where the client allows it.
Don't rely on removing
brfromAccept-Encoding. A malicious server can send Brotli anyway, and clients decode based on the response header.Shrink the blast radius. Run services that fetch untrusted URLs as unprivileged users, keep secrets out of their environment, and restrict where they can connect.
How should I prioritise HTTP2Shell fixes?
A version scanner will flag a huge share of a modern environment, all with the same CVE and the same score. That's accurate but unhelpful for deciding what to fix first. Rank by whether a stranger's Brotli data can reach the decoder:
First: services that fetch URLs chosen by users (webhooks, link previews, crawlers, AI agents), and internet-facing servers that decompress
brrequest bodies.Next: Python services with Brotli installed that call external APIs, Envoy with a Brotli decompressor, and tools that open files from outside sources.
Then: jobs that only decompress data your own systems produced, internal tools, CI runners and developer machines.
Track: end-of-life runtimes and vendor products waiting on fixes.
Why is it called HTTP2Shell?
The bug has had several names, and each one shows who the industry thought was exposed at the time:
Node2Shell (October 21): Node.js shipped the first fix, so early coverage, including our own, treated it as a Node.js bug.
Python2Shell (October 23): OpenSourceMalware and Aikido showed that the PyPI
Brotliandbrotlicffipackages compile the same C decoder.HTTP2Shell: Aikido's name once it was clear the bug lives in the shared library, putting anything that decodes Brotli over HTTP in scope. Strobes reports Bun's advisory also uses it. Broccoli2Shell is another alias.
All of them are the same bug, CVE-2026-111497. There's no second CVE.
HTTP2Shell timeline
Feb 27, 2026: Brotli fix (commit 0ed4268) lands upstream, not labelled as a security fix.
Oct 21: Node.js ships fixed releases (10:38 UTC). Google releases Brotli 1.0.10, 1.1.1 and 1.2.1. Vercel announces WAF rules.
Oct 22: CVE record and GitHub advisory published. Brotli 1.2.1 reaches PyPI. Imperva publishes its code-execution research. Bun's fix tracking issue closes, with 1.4.4 carrying the fix.
Oct 23: brotlicffi 1.2.1.0 released. Python impact research published. Envoy publishes its advisory. Debian accepts fixes for Debian 12 and 13. PYSEC entries added.
Oct 24: bundled copies in .NET, PHP, Ruby, DuckDB, ClickHouse and others still awaiting fixes, per the public tracker.
The bigger lesson
HTTP2Shell shows how one fix in one small C library has to travel separately through every runtime, package, proxy, distribution and vendor that copied it, each on its own schedule. A fix that sat unreleased for eight months is now being shipped project by project.
It's the same pattern behind PHP2Shell and the Pillow bugs this month: the code that handles bytes from strangers is usually old C code, buried a few layers below anything you chose on purpose. Find every copy, patch the ones strangers can reach, restart what's running, and keep the inventory for next time.
Sources: The Hacker News · Strobes · Aikido: Python packages and HTTP2Shell · GitHub advisory GHSA-9v8h-qqgm-4m35 · Envoy advisory GHSA-3wvj-j6qm-62mr · Debian brotli package tracker · Istio security bulletins · Node.js October 2026 security releases
Frequently asked questions
What is HTTP2Shell?
It’s the nickname for CVE-2026-111497, an out-of-bounds write in Google’s Brotli decoder (1.0.3 to 1.2.0). It affects any software that decompresses attacker-controlled Brotli data.
Are HTTP2Shell, Node2Shell and Python2Shell different bugs?
No. They’re all CVE-2026-111497. The name changed as researchers found more affected software.
Is my Python app affected if I never import Brotli?
Possibly. If Brotli or brotlicffi is installed, requests, urllib3, aiohttp and httpx decode Brotli responses automatically. Upgrade to Brotli 1.2.1 and brotlicffi 1.2.1.0, or uninstall them.
Does updating my Linux system’s libbrotli fix everything?
No. Software that bundles its own copy, such as Node.js, Bun, the .NET runtime and some database and archive tools, needs its own update.
Does a WAF protect against HTTP2Shell?
Only for incoming requests. It can’t see Brotli responses your own code fetches from other servers.
Is HTTP2Shell being exploited?
No attacks in the wild had been reported as of October 24, 2026. However, code execution has been shown in a lab on an official Node.js build.



