Testing methodology →

CVE-2026-111497  ·  Dev check  ·  Tests

HTTP2Shell: Brotli decoder CVE
Are you affected?

Attackers are exploiting a bug in Google's Brotli decoder that lets crafted compressed data crash a server, leak memory or run code, with no login. If your service runs on Node.js, Bun, Electron, Python, .NET, Java or curl, you may be affected. Jump to the checks.

TL;DR

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(), Python urllib3, 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, httpx and aiohttp via the Brotli and brotlicffi packages. Unrelated to HTTP/2.
  • Python2Shell: the flaw in Python's Brotli and brotlicffi packages, 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/brotli has the same flaw, but in Go it can only crash the process. Fixed in v1.2.7. See the Go row.

Manual checks

Any row that matches means you are affected.

StackCheckAffected ifFix
Node.js
node --version
  • 22.x below 22.23.4
  • 24.x below 24.22.1
  • 26.x below 26.12.1
  • Any 20.x, 23.x, 25.x or older (no fix)
  • 22.23.4, 24.22.1 or 26.12.1
  • Move end-of-life lines to a supported one
Bun
bun --version
  • 1.0.21 to below 1.4.4
  • 1.4.4
  • Rebuild bun build --compile binaries
Electron
npm ls electron
in your app's repo
plutil -extract CFBundleVersion raw -o - "/Applications/NAME.app/Contents/Frameworks/Electron Framework.framework/Resources/Info.plist"
an installed macOS app
  • Any release below 42.0.0
  • 42.0.0 or later
  • Rebuild and ship the app. For apps you only use, wait for the vendor's update
.NET
dotnet --list-runtimes
compare runtime versions
  • 8 below 8.0.33
  • 9 below 9.0.22
  • 10 below 10.0.14
  • 11 previews and RCs before 11.0.0-rc.3.26522.148
  • 8.0.33, 9.0.22 or 10.0.14
  • 11.0.0-rc.3.26522.148
  • Rebuild self-contained and NativeAOT apps
Python
pip list 2>/dev/null | grep -iE '^(brotli|brotlicffi|curl[-_]cffi) '
in every venv
  • Brotli below 1.2.1
  • brotlicffi below 1.2.1.0
  • curl_cffi below 0.17.0
  • 1.2.1
  • 1.2.1.0
  • 0.17.0
Java
mvn dependency:tree -Dincludes=com.aayushatharva.brotli4j
./gradlew -q :app:dependencyInsight --dependency com.aayushatharva.brotli4j --configuration runtimeClasspath
once per module, replacing :app
  • brotli4j 1.23.0 or earlier
  • jvmbrotli, any version
  • 1.24.0 for brotli4j and every native-* artifact
  • Replace jvmbrotli
Ruby
grep -E '^ brotli \(' Gemfile.lock
  • brotli gem 0.2.1 to 0.9.0
  • 0.9.1
Go
go list -m all | grep brotli
  • andybalholm/brotli below v1.2.7 (same flaw, crash only)
  • google/brotli (cbrotli) links the build host's libbrotli: check the Linux rows
  • andybalholm/brotli v1.2.7
  • cbrotli: patch the OS library and restart
  • Rebuild if linked statically or shipped in an image
  • Bazel: move @org_brotli to 1.2.1 and rebuild
Rust
grep -i brotli Cargo.lock
  • brotlic-sys 0.2.2 or earlier (via brotlic 0.8.2 or earlier)
  • compu-brotli-sys 1.2.1 or 1.0.10
  • Any other -sys crate that vendors an unfixed decoder
  • Not affected: pure-Rust brotli, brotli-decompressor
  • Move to the pure-Rust crates
  • No fixed -sys release on crates.io
curl
curl -V | grep -io 'brotli/[0-9.]*'
  • brotli/1.0.3 to 1.2.0
No brotli/ in the output: not affected
  • Patch the OS libbrotli and restart (see the Linux rows)
  • Builds with their own Brotli: upgrade curl
Debian / Ubuntu
dpkg -l | grep brotli
  • Debian bookworm: below 1.0.9-2+deb12u1
  • Debian trixie: below 1.1.0-2+deb13u1
  • Debian forky: no fix yet
  • Debian sid: below 1.2.0-4.1
  • Debian bullseye: below 1.0.9-2+deb11u1 (Freexian ELTS, paid)
  • Debian buster: below 1.0.7-2+deb10u2 (Freexian ELTS, paid)
  • Ubuntu 26.10: below 1.2.0-4ubuntu0.1
  • Ubuntu 26.04: below 1.2.0-3ubuntu0.1
  • Ubuntu 24.04: below 1.1.0-2ubuntu0.1
  • Ubuntu 22.04: below 1.0.9-2ubuntu0.1
  • Ubuntu 20.04: below 1.0.7-6ubuntu0.1+esm1 (Ubuntu Pro)
  • Ubuntu 18.04: below 1.0.3-1ubuntu1.3+esm1 (Ubuntu Pro)
  • Ubuntu 16.04: below 1.0.3-1ubuntu1~16.04.2+esm1 (Ubuntu Pro)
  • Security update
  • Restart what links it
Other Linux
rpm -qa | grep brotli
apk info -v | grep brotli
pacman -Q brotli
  • Upstream 1.0.3 to 1.0.9, 1.1.0 or 1.2.0
  • Fedora, Arch, Alpine 3.21+, openSUSE Tumbleweed: the version is enough (they ship 1.1.1 or 1.2.1)
  • Alpine 3.20 and 3.19: no fix
  • Fedora 43: fix in updates-testing only
  • RHEL, AlmaLinux, Amazon Linux, SLE: compare the release string (see notes)
  • RHEL 10: 1.1.0-8.el10_2.1
  • RHEL 9: 1.0.9-10.el9_8.1
  • RHEL 8: 1.0.6-5.el8_10
  • Amazon Linux 2023: 1.1.0-1.amzn2023.0.2
  • SLE 15 SP4 to SP7: 1.0.7-150200.3.8.1
  • Restart what links 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.

Caveats per stack

Exceptions to the table above. Read the rows for the stacks you run.

Electron

CaseWhat to know
Whose Brotli
  • Electron links Chromium's Brotli, not Node.js's.
  • The Node.js version inside an app tells you nothing.
Fixed in
  • Electron 42 is the first release built on Chromium 148, which carries the fix.
Fix
  • Each app ships its own Electron, so the only fix is a new build of the app.

curl

CaseWhat to know
Version output
  • curl -V prints the upstream Brotli version, even when a distro has patched the library.
  • Judge a system curl by the OS package.
Other users
  • git and other dynamically linked libcurl users inherit the same library. Windows and static builds bundle their own.

.NET

CaseWhat to know
PowerShell
  • 7.4, 7.5 and 7.6 are affected.
  • Fixed in 7.4.22, 7.5.13 and 7.6.9.
Visual Studio
  • 2019 16.11: fixed in 16.11.61
  • 2022 17.14: fixed in 17.14.43
  • 2026 18.11: fixed in 18.11.2
  • 2017 15.9: no fixed build listed
  • Build numbers come from Microsoft's fixed-build list (MSRC).

Python

CaseWhat to know
Direct dependents
  • Scrapy, flask-compress, selenium-wire and django-compression-middleware depend on Brotli directly.
Through extras
  • urllib3 (and so requests), httpx and aiohttp pull 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.
Wheels with their own Brotli
  • Pillow 13.0.0 wheels bundle libbrotli 1.2.0, and no fixed Pillow release exists yet.
  • duckdb vendors Brotli 1.1.0, below the fixed 1.1.1.
  • The pip versions of these packages don't map to Brotli versions.
Distro python3-brotli
  • Shows the upstream version even after patching.
  • Use the OS row.
  • Debian's python-brotlicffi is affected too: trixie is vulnerable, forky and sid are fixed.

Java

CaseWhat to know
jvmbrotli
  • com.nixxcode.jvmbrotli has had no release since 2019 and bundles Brotli 1.0.7.
  • Replace it.

Ruby

CaseWhat to know
brotli gem
  • From 0.4.0 it links the system libbrotli if libbrotli-dev was present at install.
  • Those builds are fixed by the OS update.

Go

CaseWhat to know
cbrotli
  • Has no C code of its own. cgo links the build host's libbrotli.
  • Patch the OS library and restart.
Bazel
  • Builds compile @org_brotli from source.
  • Move it to 1.2.1 and rebuild.

Rust

CaseWhat to know
brotlic-sys
  • Bundles Brotli 1.0.9.
compu-brotli-sys
  • 1.2.1 and 1.0.10 bundle the unfixed 1.2.0 and 1.0.9 decoders despite their version numbers.
  • No release of the crate is fixed, and its 1.2.0 release is yanked.
Other -sys crates
  • Judge them by their vendored source: fixed code contains BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH.
  • Grep Cargo.lock, because plain cargo tree shows only the host target.

Linux and OS packages

CaseWhat to know
Debian and Ubuntu nodejs
  • Debian's package, and Ubuntu's on 22.04 and later, use the system libbrotli.
  • node --version alone tells you nothing there. Check the Debian / Ubuntu row.
  • Debian's tracker still lists nodejs as vulnerable on bookworm, trixie and forky. Only sid is fixed.
Ubuntu 20.04 nodejs
  • 10.19 bundles its own Brotli and has no fix.
  • Updating libbrotli1 doesn't cover it.
Debian bookworm
  • No fixed build for armel, mips64el, mipsel or s390x.
RHEL, AlmaLinux, Amazon Linux, SLE
  • They keep the old version number when they patch.
  • 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.
  • Firefox, Thunderbird, and the RHEL 8/9 nodejs:24 modules.
  • SUSE lists ghostscript, qemu, ovmf, texlive and mozjs as affected.

Scanners and containers

CaseWhat to know
Silent scanners
  • Brotli4j, the Ruby gem, curl_cffi and the Rust -sys crates have no package-level advisory in the GitHub Advisory Database, OSV or RustSec.
  • Bun has a repository advisory (GHSA-663w-cv8g-jj2p) that is not in the global database yet. OSV lists Bun and andybalholm/brotli only as git ranges, which package scanners may not match.
  • Dependabot, OSV-Scanner, govulncheck, bundler-audit and cargo audit may miss all of these. Check the versions yourself.
Container images
  • Run the same checks inside every image you ship, for example docker run --rm --network=none <image> node --version (or podman run).
  • Updating the host does not fix an image. Rebuild it.

Vulnerability checker

We've provided an open-source vulnerability checker that runs every check on this page against your machine in a single pass. It's read-only, makes no changes on your system. It reports vulnerable libraries, runtimes and packages. Usage is in the repository README.

It scans:

Usage

# Get the script
git clone https://github.com/fieldse/brotli-http2shell-checker.git
cd brotli-http2shell-checker
less scripts/vuln-check-CVE2026-111497-brotli.sh   # review before running

# Run it
./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 exits 1 on any WARN, so it can be used for a CI gate.

Project source

View at GitHub

View source: vuln-check-CVE2026-111497-brotli.sh.

Table of what it checks.

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

Resources

Write-ups for background, exposure paths and detection.