CVE-2026-111497 — Google Brotli Unchecked Return Value Vulnerability

CVE-2026-111497

Google Brotli - Broccoli2Shell, Out-of-Bounds Write in the Block-Switch Decoder

What is Google Brotli?

Brotli is Google's general-purpose compression algorithm, published in 2015 and now the default way the web compresses text. When a browser sends Accept-Encoding: br and a server answers with Content-Encoding: br, both ends are running Brotli's reference C implementation or a binding to it.

That reference library, google/brotli, is a dependency almost nobody tracks deliberately. It is statically linked into Node.js, Bun, and the .NET runtime; it backs Python's Brotli and brotlicffi packages, which urllib3, requests, httpx, aiohttp, and Scrapy pull in transparently; it is compiled into Envoy and therefore into Istio; it ships inside Windows builds of PHP. A defect in a few hundred lines of decoder C is simultaneously a defect in every one of those, and the version string of the product tells you nothing about which Brotli it contains.

Overview

CVE-2026-111497, known variously as Broccoli2Shell, Node2Shell, and HTTP2Shell, is an out-of-bounds write in the Brotli decoder reachable from any attacker-controlled compressed stream. It affects both directions of HTTP: a server that decompresses a request body with Content-Encoding: br, and a client that decompresses a response from a host the attacker controls or can influence. Outcomes range from a process crash to process memory disclosure to full remote code execution.

CISA added the CVE to KEV on 2026-10-27. Whether exploitation is widespread is genuinely contested at the time of writing. ELLIO reported exploit traffic against its sensors on 2026-10-26; Tenable has not independently confirmed that activity, and CyberScoop quoted researchers who had seen no exploitation on real networks. Public proof-of-concept code exists, and Imperva demonstrated code execution against Node.js 24.22.0 on Linux arm64 without releasing the exploit.

No NVD CVSS score had been published when this page was written, which is why no rating is shown above. Google, as CNA, scored it 9.2 under CVSS v4.0 (CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N). Microsoft scored its .NET exposure 8.1 under CVSS v3.1.

Affected Versions

Product Vulnerable Fixed
Google Brotli (C library) 1.0.3 through 1.0.9, 1.1.0, 1.2.0 1.0.10, 1.1.1, 1.2.1
Node.js < 22.23.4, < 24.22.1, < 26.12.1 22.23.4, 24.22.1, 26.12.1
Node.js 20.x, 23.x, 25.x All (end of support) No fix; move to a supported line
Bun 1.0.21 up to but excluding 1.4.4 1.4.4
.NET 8 / 9 / 10 / 11 < 8.0.33, < 9.0.22, < 10.0.14, < 11 RC3 8.0.33, 9.0.22, 10.0.14, 11 RC3
Envoy Proxy <= 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 < 1.29.9, < 1.30.6, < 1.31.2 1.29.9, 1.30.6, 1.31.2
Python Brotli / brotlicffi 1.0.3 to 1.2.0 / 1.0.3 to 1.2.0.x 1.2.1 / 1.2.1.0
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 < 0.21.1 0.21.1

Reported but less severe: FFmpeg by way of libjxl showed instruction-pointer control without demonstrated execution, Apache Arrow hangs in an infinite loop, and a ClickHouse server crashed, with that fix merged but unreleased as of 2026-10-26.

Technical Details

The CWE chain is CWE-252, unchecked return value, leading to CWE-787, out-of-bounds write. In plain words: a helper function reported failure in a way the caller could not interpret, so the caller drew the wrong conclusion and kept writing.

Brotli streams are divided into blocks, and each block kind carries its own block-type table and a countdown. When the counter reaches zero the decoder reads a block switch. The block-switch helper returned a bare boolean, and it returned false for two unrelated conditions: a malformed switch, such as one declaring only a single block type, and a legitimate shortage of input. The caller could not tell them apart, assumed the second, and asked for more bytes. An invalid switch never drains the decoder's eight-byte buffer, so the decoder keeps going and its writes eventually land past the end of that buffer. The fix, commit 0ed4268a, returns a distinct error code, BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH (-17).

The bug was introduced in Brotli 1.0.3 in March 2018 and sat in the code for over eight years. Exploitation needs no authentication and no user interaction, and is a single request, but it is not trivially universal: ELLIO found success depends on the accepted socket file descriptor number and a per-build memory offset. Official Node.js builds are non-PIE, so the offset is stable within a given build, but an offset tuned for 24.22.0 failed against 22.23.3 and 26.12.0 across 10,000 attempts. Failures usually crash the worker, and a restart supervisor simply hands the attacker another attempt. Some bindings behave differently again: Python Brotli, brotlicffi, the PHP streaming API, and the Ruby gem's Decompressor#process return no bytes and hang indefinitely rather than crashing.

Discovery

Google committed the fix to brotli master on 2026-02-27 with no release, no CVE, and no advisory, which is how a security patch spent eight months sitting in public source control while every downstream consumer kept shipping the vulnerable build. The coordinated disclosure arrived on 2026-10-21 through the Node.js security release, alongside Google's tagged Brotli releases.

Reporting credit is attributed to Khai Tran and Sylvie Mayer of OpenAI Codex Security, with the Node.js-side fixes implemented by Matteo Collina and Antoine du Hamel; this attribution comes from secondary coverage rather than a vendor acknowledgements page. Envoy and Istio shipped their fixes earlier in October without naming the flaw.

Exploitation Context

ELLIO reports two distinct phases. In mid-June 2026, months before public disclosure, its sensors logged a scanner from AS44620 in Turkey using the user agent node2shell-check/1.0, sending 20 POST bodies with Content-Encoding: br in two bursts: five malformed, fifteen valid Brotli at four stream sizes up to 65,743 bytes. That is fingerprinting, not exploitation, and its purpose was to build a list of hosts that decode Brotli.

On 2026-10-26 a different source, 94.154.43.7, delivered a 23,069,983-byte Brotli body targeting Node.js v24.22.0 on x86-64. ELLIO assesses the ROP chain as original work rather than a copy of a public PoC, and notes it scored zero shells in 50 attempts against a vulnerable target in their own testing. The body hashes to SHA-256 7fcbdaaecd4419e2930927844f3b772668204737a4e7602a2290c991c93c5c4b. The pattern, a pre-disclosure target list followed by an untargeted single-build payload, is consistent with an operator preparing for mass exploitation rather than one already succeeding at it.

No threat actor has been named and no ransomware use has been reported. The secondary risk deserves attention even where code execution fails: a crashed worker can write a core dump containing live session data, credentials, or key material.

Remediation

  1. Patch the runtime, not the library. Update Node.js to 22.23.4, 24.22.1, or 26.12.1; Bun to 1.4.4; .NET to 8.0.33, 9.0.22, 10.0.14, or 11 RC3; Envoy and Istio to their listed releases; Python Brotli to 1.2.1 and brotlicffi to 1.2.1.0; Windows PHP to the rebuilt -1 binaries and the brotli extension to 0.21.1.
  2. Restart every process and scheduled job after patching, and rebuild and redeploy container images. A pinned vulnerable base image keeps shipping the old decoder, and Bun --compile executables and .NET NativeAOT or self-contained builds must be rebuilt.
  3. Find bundled copies. Any application statically linking its own Brotli needs its own fix; a patched system package does not help it.
  4. On Node.js 20.x, 23.x, or 25.x there is no patch. Move to a supported line.
  5. Until patched, reject Content-Encoding: br request bodies at the proxy or load balancer. Understand the limit: this protects servers that decompress inbound data, and does nothing for clients fetching Brotli responses from an attacker-influenced URL.
  6. For client-side exposure, disable Brotli decoding in the HTTP client itself. Removing br from Accept-Encoding is not sufficient, since a server can send it anyway. In Envoy and Istio, disable the Brotli decompressor filter in both directions. Remove the Brotli and brotlicffi packages from Python environments that do not need them.
  7. Turning off Brotli compression on your origin or CDN does nothing, because the risk is in decompression.
  8. Review logs for POST bodies with Content-Encoding: br, for the scanner user agent node2shell-check/1.0, and for traffic from 94.154.43.7. Treat repeated worker crashes or hangs during decompression as a possible attempt, and disable core dumps on exposed services or ensure they are not world-readable.
  9. Federal civilian agencies must remediate by 2026-11-10 under BOD 22-01.

Key Details

PropertyValue
CVE ID CVE-2026-111497
Vendor / Product Google — Brotli
CVSS 3.1 ScorePending
SeverityUNKNOWN
CISA KEV Added2026-10-27
CISA KEV Deadline2026-11-10
Known Ransomware Use No

Required Action

CISA BOD 22-01 Deadline: 2026-11-10. Apply mitigations in accordance with vendor instructions, ensuring compliance with CISA’s BOD 26-04 Prioritizing Security Updates Based on Risk (see URL in Notes) guidance and CISA’s “Forensics Triage Requirements” (see URL in Notes). Follow applicable BOD 26-04 guidance for cloud services or discontinue use of the product if mitigations are unavailable. Stakeholders are responsible for evaluating each asset's internet exposure and ensuring adherence to BOD 26-04 patching guidelines.

Timeline

DateEvent
2026-02-27Google commits the fix to brotli master with no release and no advisory
2026-10-21Node.js discloses the flaw in its security release; Google ships Brotli 1.0.10, 1.1.1 and 1.2.1
2026-10-22CVE-2026-111497 published; fixed Python Brotli and brotlicffi packages reach PyPI
2026-10-25Microsoft issues out-of-band .NET updates for 8, 9, 10 and 11
2026-10-26ELLIO sensors record exploit traffic targeting Node.js 24.22.0 on x86-64
2026-10-26PHP publishes rebuilt Windows binaries bundling fixed Brotli
2026-10-27Added to CISA Known Exploited Vulnerabilities catalog
2026-11-10CISA BOD 22-01 remediation deadline