The bug
- What it is
- An out-of-bounds write in the decoder of Brotli, Google's compression library, versions 1.0.3 to 1.2.0 (CVE-2026-111497). Runtimes and packages use it to unpack Brotli-compressed HTTP data.
- Fixed upstream in 1.0.10, 1.1.1 and 1.2.1, all released 2026-10-21.
- Every runtime, package or library that bundles or links that decoder inherits it.
- Impact
- Remote code execution, memory leaks or crashes. The CVE record rates it 9.2 Critical (CVSS 4.0). Node.js and Microsoft rate it High.
- Under active attack. CISA added it to its Known Exploited Vulnerabilities list on 2026-10-27.
- No login needed. Any app that decodes attacker-supplied Brotli is reachable: a request body sent with
Content-Encoding: br(Express 5, Koa body parsers,node:zlib) or a response fetched from a server the attacker controls (fetch(), Pythonurllib3,httpx,aiohttp). Clients are exposed as well as servers. - Code execution is proven on stock Node.js 24.22.0. Failed attempts crash the process, and each build needs its own offsets.
- Names
- Node2Shell: the flaw in the Node.js runtime, reached through Brotli request bodies.
- HTTP2Shell: the flaw in any HTTP client or server that decodes Brotli, such as Python's
urllib3,requests,httpxandaiohttpvia theBrotliandbrotlicffipackages. Unrelated to HTTP/2. - Python2Shell: the flaw in Python's
Brotliandbrotlicffipackages, which compile the same C decoder. - Brotli2Shell, Broccoli2Shell, Brotlipocalypse: names for the decoder flaw itself.
- Exploitation
- Attacks started within a day of disclosure. Vendor sensors have logged attempts from at least 20 IPs since 2026-10-21.
- No confirmed compromise yet. ELLIO replayed a captured exploit chain 50 times in a lab and got no shell.
- Public exploit code has been out since 2026-10-22.
- Related
- The pure-Go
andybalholm/brotlihas the same flaw, but in Go it can only crash the process. Fixed in v1.2.7. See the Go row.
- The pure-Go
Manual checks
Any row that matches means you are affected.
| Stack | Check | Affected if | Fix |
|---|---|---|---|
| Node.js | node --version |
|
|
| Bun | bun --version |
|
|
| .NET | dotnet --list-runtimes |
|
|
| Python | pip list 2>/dev/null | grep -iE '^(brotli|brotlicffi|curl[-_]cffi) ' |
|
|
| Java | mvn dependency:tree -Dincludes=com.aayushatharva.brotli4j./gradlew -q :app:dependencyInsight --dependency com.aayushatharva.brotli4j --configuration runtimeClasspath:app |
|
|
| Ruby | grep -E '^ brotli \(' Gemfile.lock |
|
|
| Go | go list -m all | grep brotli |
|
|
| Rust | grep -i brotli Cargo.lock |
|
|
| Debian / Ubuntu | dpkg -l | grep brotli |
|
|
| Other Linux | rpm -qa | grep brotliapk info -v | grep brotlipacman -Q brotli |
|
|
- .NET: Microsoft also lists PowerShell 7.4, 7.5 and 7.6 (fixed in 7.4.22, 7.5.13 and 7.6.9) and Visual Studio 2019 16.11 (16.11.61), 2022 17.14 (17.14.43) and 2026 18.11 (18.11.2). Visual Studio 2017 15.9 has no fixed build listed.
- Python: Scrapy, flask-compress, selenium-wire and django-compression-middleware depend on Brotli directly.
urllib3(and sorequests),httpxandaiohttppull it in only through extras (urllib3[brotli],httpx[brotli],aiohttp[speedups]). They still decode Brotli whenever it is importable.pipdeptree -r -p Brotli,brotlicffi --extras active(pipdeptree 3.0+) shows what pulls it in. - Python wheels with their own Brotli: Pillow 13.0.0 wheels bundle libbrotli 1.2.0, and no fixed Pillow release exists yet. duckdb vendors an unfixed Brotli 1.1.0 decoder. The pip versions of these packages don't map to Brotli versions.
- Distro-installed
python3-brotlishows the upstream version even after patching. Use the OS row. - Java:
jvmbrotli(com.nixxcode.jvmbrotli) is abandoned and bundles Brotli 1.0.7. Replace it. - Ruby: from 0.4.0 the
brotligem links the system libbrotli iflibbrotli-devwas present at install. Those builds are fixed by the OS update. - Go cbrotli has no C code of its own. cgo links the build host's libbrotli, so patch the OS library and restart. Bazel builds compile
@org_brotlifrom source, so move that to 1.2.1 and rebuild. - Rust:
brotlic-sysbundles Brotli 1.0.9.compu-brotli-sys1.2.1 and 1.0.10 bundle the unfixed 1.2.0 and 1.0.9 decoders despite their version numbers. Its only fixed release, 1.2.0, is yanked. Judge any other-syscrate by its vendored source: fixed code containsBROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH. GrepCargo.lock, because plaincargo treeshows only the host target. - Debian's
nodejspackage, and Ubuntu's on 22.04 and later, use the systemlibbrotli, sonode --versionalone tells you nothing there. Check the Debian / Ubuntu row. Ubuntu 20.04'snodejs10.19 bundles its own Brotli and has no fix. Updatinglibbrotli1doesn't cover it. - Debian bookworm has no fixed build for armel, mips64el, mipsel or s390x.
- RHEL, AlmaLinux, Amazon Linux and SLE keep the old version number when they patch, so compare the full release string (e.g.
1.0.9-10.el9_8.1) against the vendor tracker, not the upstream version. - Bundled copies on RPM distros: some packages bundle their own Brotli and won't show in
rpm -qa | grep brotli. These include Firefox, Thunderbird, the RHEL 8/9nodejs:24andnodejs:26modules, and on SUSE ghostscript, qemu, ovmf, texlive and mozjs. - Scanners stay silent for several of these. Bun, Brotli4j, the Ruby gem, curl_cffi,
andybalholm/brotliand the Rust-syscrates have no entry in the GitHub Advisory Database, OSV, the Go vulnerability database or RustSec. Dependabot, OSV-Scanner, govulncheck, bundler-audit and cargo audit won't flag them. - Containers: run the same checks inside every image you ship, for example
docker run --rm --network=none <image> node --version(orpodman run). Updating the host does not fix an image. Rebuild it.
Vendored Brotli source
If you vendor Brotli's C source, fixed code contains the error name BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH. This lists decoder files that lack it:
grep -rIlZ --include='decode.c' --include='decode.cpp' 'BrotliDecoderDecompressStream' . | xargs -0 -r grep -L 'BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH'
Copies older than 1.0.3 also show up but are not affected.
The Debian and Ubuntu security patches add the same error name. Compiled libraries show it as _ERROR_FORMAT_BLOCK_SWITCH (1.1 and later) or a bare BLOCK_SWITCH (1.0.x). Still judge OS packages by version.
Automated checker
We provide a free script that runs every check on this page against one machine in a single pass. With -c it also checks local Docker or Podman images. It reads files and makes no changes. Usage is in the repository README.
git clone https://github.com/fieldse/brotli-node2shell-check.git cd brotli-node2shell-check less scripts/vuln-check-CVE2026-111497-brotli.sh # review before running
View the script source: vuln-check-CVE2026-111497-brotli.sh.
./scripts/vuln-check-CVE2026-111497-brotli.sh -r ~/src -q # scan a source tree and report problems only ./scripts/vuln-check-CVE2026-111497-brotli.sh -r /srv -c # also check local Docker or Podman images ./scripts/vuln-check-CVE2026-111497-brotli.sh -c -e podman # set the engine (by default Docker, then Podman) ./scripts/vuln-check-CVE2026-111497-brotli.sh --help
- FAIL
- A known-vulnerable version is present.
- WARN
- Needs manual review.
The script exits 1 on any FAIL. With --strict it also exits 1 on any WARN, so it can gate CI.
If you can't upgrade today
Reject request bodies with Content-Encoding: br at your proxy or gateway. This doesn't protect code that fetches Brotli responses from user-supplied URLs, so upgrade as soon as you can.
Sources
Versions on this page come from these advisories, checked on 2026-10-29.
Every version claim with its source
- CVE-2026-111497 record
- Google Brotli v1.0.10 release
- Google Brotli v1.1.1 release
- Google Brotli v1.2.1 release
- Node.js October 2026 security releases
- Bun GHSA-663w-cv8g-jj2p
- .NET announcement #494
- Microsoft MSRC CVE-2026-111497
- PyPI Brotli, brotlicffi GHSA-9v8h-qqgm-4m35
- curl_cffi v0.17.0 release notes
- Brotli4j GHSA-x524-jrqf-vwq6
- andybalholm/brotli GHSA-c9gr-gmg4-2vqv
- Debian security tracker
- Debian DLA-4855-1
- Debian DSA-6582-1
- Freexian ELA-1861-1
- Ubuntu CVE tracker
- Ubuntu USN-8956-1
- Red Hat CVE page
- SUSE CVE page
- Alpine security tracker
- Fedora Bodhi brotli updates
- Amazon Linux ALAS2023-2026-3334
- Envoy GHSA-3wvj-j6qm-62mr
- Istio ISTIO-SECURITY-2026-007
Resources
Write-ups for background, exposure paths and detection.
- OpenSourceMalware: CVE-2026-111497 Brotli bug reaches far beyond Node.jsInventory of projects that bundle their own Brotli copy, and the fix-marker string.
- OpenSourceMalware: Python packages vulnerable to Node2ShellAffected PyPI packages and how to find them.
- Socket: eMudhra, Brotli, and the long tail of a security fixWhy vendored copies keep the bug alive after the upstream fix.
- Aikido: Node2Shell, Node.js Brotli RCEThe Node.js case and its exposure paths.
- Aikido: Python packages vulnerable, evolves to HTTP2ShellWhere the HTTP2Shell name comes from.
- Wiz: Broccoli2Shell, everything you need to knowOverview across Node.js, Bun, Envoy and more.
- Sysdig: Detecting the Node.js Brotli RCERuntime detection.
- Tenable: Brotli2Shell FAQCommon questions, via Security Boulevard.
- broccoli2shell.comCommunity tracker of affected projects.
- Blacklight SecurityPenetration testing, managed SOC and incident response in Australia and New Zealand.