TL;DR
HTTP2Shell (CVE-2026-111497) is an out-of-bounds write in Google’s Brotli decoder, versions 1.0.3 through 1.2.0. An unauthenticated attacker who gets crafted Brotli data into a vulnerable decoder can crash the process, read its memory, or in some cases run code. It was first reported as a Node.js bug (“Node2Shell”), but the flaw is in the shared C library, so Python, Bun, curl, Envoy, Istio and other HTTP software are affected too.
- The CVE record scores it 9.2 (CVSS 4.0).
- It works in both directions: a malicious client can attack a server, and a malicious server can attack a client.
- Researchers have shown code execution on an official Node.js build. As of October 23 there were no reports of exploitation in the wild, and it isn’t in CISA KEV.
- Patch Brotli, Node.js and the Python packages (versions below), rebuild images, and restart services.
What happened
Node.js disclosed and patched the bug on October 21, and Imperva’s Red Team showed it running code on an unmodified Node.js 24.22.0 build. A day later, GitHub advisory GHSA-9v8h-qqgm-4m35 confirmed that the Python packages Brotli and brotlicffi carry the same decoder. By October 23 people had started calling it HTTP2Shell, and Bun used that name in its October 24 advisory.
OpenAI reported the bug in February, and Brotli fixed the code then. Nobody treated it as a security fix, so no release shipped it until October. Every project that bundles its own copy of Brotli now has to put out an update, and some still haven’t.
How the bug works
The problem is in DecodeBlockTypeAndLength() in c/dec/decode.c, an unchecked return value (CWE-252) that leads to an out-of-bounds write (CWE-787). The function handles block switches, the points where a stream changes Huffman tree. It returns a plain boolean, so “this stream is malformed” and “I need more input” look the same to the caller, and the fast path ignores the result anyway.
A crafted stream declares one block type and runs its length down to zero, which forces a switch that can’t succeed. The decoder then either keeps asking for input on a finished stream or keeps decoding with stale state. The second case writes past a small working buffer, and that corruption is what leads to memory leaks and code execution. The payload still works when split into tiny chunks, so HTTP/2 framing doesn’t break it up.
fixes it by returning a real error code, BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH (-17), on both paths.
Attacker data can reach the decoder in three ways:
- A client sends a request body with Content-Encoding: br, and the server or proxy decompresses it before any authentication.
- The app fetches a URL (a webhook, link preview, crawler or URL import) and the server replies with a Brotli body. Dropping br from Accept-Encoding doesn’t help, because many clients pick the decoder from the response header.
- Code decompresses uploaded files or other untrusted data directly.
Affected versions
Any build with Brotli 1.0.3 through 1.2.0 is affected, except the fixed releases 1.0.10 and 1.1.1. Checked against vendor advisories on October 24, 2026.
- Google Brotli / libbrotli – 1.0.3 through 1.2.0 (fixed in 1.2.1, 1.1.1, 1.0.10)
- Node.js – 22.x, 24.x, 26.x before the fix (fixed in 22.23.4, 24.22.1, 26.12.1; EOL lines 20, 23, 25 get no fix)
- Brotli (PyPI) – 1.0.3 up to 1.2.1 (fixed in 1.2.1)
- brotlicffi (PyPI) – 1.0.3 up to 1.2.1.0 (fixed in 1.2.1.0)
- Bun – 1.0.21 up to 1.4.4 (fixed in 1.4.4; rebuild compiled executables)
- Envoy – 1.39.2, 1.38.5, 1.37.7, 1.36.11 (fixed in 1.40.0, 1.39.3, 1.38.6, 1.37.8, 1.36.12; only with the Brotli decompressor configured)
- Istio – unconfirmed (reported fixes 1.29.9, 1.30.6, 1.31.2; no Istio bulletin yet)
- curl / libcurl – builds linking a vulnerable Brotli (rebuild against fixed Brotli)
- Debian brotli, nodejs – bookworm, trixie, forky, sid (not fixed yet)
- Amazon Linux 2023 – brotli, nodejs24 (fix pending; nodejs and nodejs20: no fix planned)
Python apps can be exposed without importing Brotli. urllib3 (and so requests), aiohttp, and httpx with the brotli extra decode it automatically when it’s installed, and Scrapy installs it by default. On October 23, pip-audit, Dependabot and Safety still didn’t flag the PyPI packages, because advisory databases hadn’t mapped the CVE to them yet. Apache mod_brotli and Nginx don’t decode Brotli request bodies by default.
What to do
Start with internet-facing proxies and services that decode request bodies, then services that fetch URLs you don’t control, then the rest. In Kubernetes, check Envoy and Istio gateways and sidecars as well: a vulnerable proxy is exposed even when the app behind it is patched. Code execution inside a pod also hands the attacker its service account token, mounted secrets and cloud identity.
- Find every copy of Brotli in SBOMs, images and hosts, including bundled and static ones. In Python, run pip show Brotli brotlicffi and pipdeptree -r -p Brotli. For Node.js, check the version each running workload reports, not just what the Dockerfile pins.
- Upgrade to the fixed versions above, or install your OS vendor’s security update.
- Regenerate lockfiles, rebuild images and binaries, redeploy, and restart. A running process keeps the old decoder in memory until it restarts.
- Check that the running workloads report the patched versions.
If you can’t patch yet, reject requests with br in Content-Encoding at the proxy or middleware, and refuse Brotli responses before your HTTP client decodes them. In Python, uninstalling Brotli and brotlicffi makes clients fall back to gzip and deflate. WAF rules, such as the ones Imperva shipped, only cover inbound traffic.
On the detection side, watch for crashes in Node.js, Python or proxy processes after br traffic, unusually large or slow Brotli bodies, web runtimes spawning shells or opening unexpected outbound connections, and pods using credentials they normally don’t touch.
Upwind MDR coverage
Our Upwind MDR team has already incorporated the known HTTP2Shell IoCs and attack patterns into our monitoring and detection workflows. We’ve added and tuned relevant detection rules, enriched our investigation logic with the available IoCs, and are actively monitoring customer environments for suspicious activity associated with exploitation attempts.
We’ll continue updating our coverage as new IoCs, exploitation techniques, and research become available.
