โ† Back

CVE-2026-111497: Critical Google Brotli Flaw Enables Remote Code Execution and Is Already Being Exploited

Clara Bishop
CVE-2026-111497: Google Brotli Decoder Flaw Reaches Node.js, Bun, Envoy, Istio and Python
Image: threat-intelligence.redeyesecurity.com

The library that quietly shrinks a huge share of the modern web just became an emergency patch. On October 21, 2026, Google shipped Brotli 1.2.1, 1.1.1, and 1.0.10 to close CVE-2026-111497, an out-of-bounds write in the Brotli decoder that a remote, unauthenticated attacker can trigger with a crafted compressed stream. Google scored the flaw 9.2 on CVSS 4.0. By October 27 it was on CISA's Known Exploited Vulnerabilities catalog, with U.S. federal agencies told to remediate by November 10.

Security teams have been calling it Node2Shell, Broccoli2Shell, and HTTP2Shell. The nicknames are catchy. The exposure is not. Brotli is embedded in browsers, language runtimes, proxies, and application stacks that decompress Content-Encoding: br traffic every day. Updating one package does not update the copies vendors bundle themselves.

What happened, and why the clock is short

Google's CVE record describes a buffer overflow in c/dec/decode.c affecting Brotli 1.0.3 through 1.2.0 on every platform. A remote attacker who does not need an account can corrupt adjacent decoder state, disclose memory, crash the process, or potentially execute arbitrary code, provided the target actually decompresses attacker-controlled Brotli data.

Oct 27 Advisory: Google Brotli Decoder Out-of-Bounds Write [CVE-2026-111497] - Censys
Image: censys.com

The finders are Khai Tran and Sylvie Mayer of OpenAI Codex Security, who uncovered the issue during red-team work and notified the Brotli maintainers and downstream projects. Node.js published security releases the same day Google tagged the fixed library builds: 22.23.4, 24.22.1, and 26.12.1. Public advisories followed on October 22. Microsoft patched .NET, Visual Studio, and PowerShell around October 25. CISA added the CVE to KEV on October 27 and set a due date of November 10, listing ransomware use as unknown. Canadian cyber authorities and European records have also flagged active exploitation.

Scoring is not uniform, and that disagreement matters for prioritization. Google's CNA vector is CVSS 4.0 9.2 (critical), with attack requirements marked present. Red Hat rates the issue Important, with a CVSS 3.1 score of 8.1 and high attack complexity, and has said there is no public, reliable remote-code-execution proof of concept in its assessment. Other trackers publish 9.8. Imperva's red team has reported working code execution against an unmodified Node.js 24.22.0 build. CISA's KEV listing is the operational fact: the agency only adds a flaw when it has evidence of exploitation in the wild. Treat the bug as actively used, even where a given vendor's exploitability note is more cautious.

How a bad block switch becomes an out-of-bounds write

Brotli streams are divided into blocks of three kinds: literals, insert-and-copy commands, and distances. When a stream declares only one block type for a kind, a block switch is invalid and the decoder is supposed to reject it. In vulnerable builds, the helper that handles that case returned the same failure signal it uses when the decoder simply needs more input. Callers treated the invalid switch as a temporary stall and kept feeding bytes into an eight-byte internal buffer that never drained. Writes then landed past the end of that buffer and into adjacent decoder state.

CVE-2026-111497: Google Brotli Decoder ยท Out-of-bounds Write | Threat Radar
Image: radar.offseq.com

Google maps the bug to two weaknesses: CWE-252, an unchecked return value, and CWE-787, an out-of-bounds write. On the fast path, the return value could be dropped entirely. The fix, associated with commit 0ed4268 and backports on the older release lines, makes an invalid block switch a permanent format error, BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH, instead of "need more input." A patched header defines that error code; an unpatched copy does not. Researchers have debated how reliably the path is reachable under the Brotli specification's metablock length cap. That debate does not change the vendor fix or the KEV status. Only the decoder is affected. Software that only compresses outbound Brotli, and never inflates untrusted input, is not on the vulnerable path.

Impact on web servers, browsers, and apps

Exposure is wherever an affected decoder unpacks data an attacker can influence. That includes HTTP services that accept Content-Encoding: br on requests, clients and services that automatically decompress Brotli responses, and APIs such as Node.js node:zlib or fetch() that decode Brotli for the application. Compressing your own responses does not, by itself, create the bug. A reverse proxy or service mesh that decompresses inbound Brotli does.

The blast radius is wide because Brotli is vendored, not just linked:

  • Runtimes. Node.js 22.x, 24.x, and 26.x before the October 21 builds; Bun before 1.4.4; end-of-life Node.js lines that will not receive a fix.
  • Language packages. PyPI brotli before 1.2.1 and brotlicffi before 1.2.1.0, plus Ruby gems, PHP extensions, Java JNI wrappers, and Go cgo bindings that ship the vulnerable C decoder.
  • Microsoft stack. .NET 8, 9, and 10 before 8.0.33, 9.0.22, and 10.0.14; PowerShell 7.4, 7.5, and 7.6 before 7.4.22, 7.5.13, and 7.6.9; Visual Studio builds patched in the same October wave.
  • Proxies and security gear. Envoy and Istio when Brotli decompression is enabled, with fixes on current supported branches, and PAN-OS releases that inspect Brotli. Disabling inspection can reduce exposure but also reduces visibility into compressed traffic until the inspection engine is patched.
  • Browsers and desktop apps. Red Hat lists Firefox and Thunderbird among applications that decompress untrusted Brotli. Chromium-based browsers embed their own decoder; some researchers say Chrome carried the upstream fix as early as version 148, while other vendor notes still list Chromium as in scope. Electron apps can embed both a browser engine and a Node.js runtime, so a fixed browser does not imply a fixed desktop app. Restart after updating. A downloaded binary that is never relaunched is still the old process.

Web servers such as nginx with ngx_brotli or Apache with mod_brotli are not automatically vulnerable if they only encode responses. They become relevant the moment a module, WAF, or application behind them inflates client-supplied Brotli. Distribution packages are a separate inventory problem: Debian, Ubuntu, and Red Hat have shipped or scheduled fixes, and a backport may keep the old version number while containing the patch.

Patches, the v1.2.0 decompression-bomb controls, and what to do now

The RCE fix is not "anything labeled 1.2." Brotli 1.2.0, released October 27, 2025, is inside the affected range. Google's security releases on October 21, 2026 are 1.0.10, 1.1.1, and 1.2.1. Stay on your current release line and move to the matching fixed tag rather than jumping major versions under pressure.

Version 1.2.0 did add a different, still useful control. Its changelog records Python API changes reported by Charles Chan: Decompressor.can_accept_more_data and an optional output_buffer_limit on Decompressor.process, so applications can stop unexpectedly large decompressed output. That is the practical answer to decompression-bomb denial of service, where a small compressed payload expands until memory or CPU is exhausted. Fedora and Scrapy tracking around CVE-2025-6176 pointed operators at those 1.2.0 Python hooks. They do not fix CVE-2026-111497. A stack on 1.2.0 should take both: move to 1.2.1 for the out-of-bounds write, and keep output limits so a hostile stream cannot balloon into a resource exhaustion event.

Practical steps while the November 10 KEV date is still ahead:

  • Inventory every copy, not just the system package. Search for bundled decode.c, Node.js, Bun, .NET, PowerShell, Envoy, Istio, Python wheels, and container base images. A patched OS library does not patch a runtime that vendors its own Brotli.
  • Patch internet-facing decoders first: Node.js services that accept compressed bodies or fetch remote Brotli, meshes with decompression on, and firewalls doing Brotli inspection.
  • Confirm the fix is actually present. Fixed trees define BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH. Version strings alone can lie when a distro backports the commit.
  • Until you can patch, avoid decompressing untrusted Brotli. For Bun fetch, decompress: false stops that request from advertising or decoding br. Equivalent limits on Node.js zlib Brotli APIs reduce exposure but are not a substitute for the runtime update.
  • Cap decompressed output even after the RCE patch. The 1.2.0 Python limits, and equivalent application-level quotas, remain the right control against decompression bombs.
  • After patching, restart processes and rebuild images. Lockfiles that still pin brotli<1.2.1 will reinstall the vulnerable wheel on the next build.

What this means for web security

CVE-2026-111497 is a reminder that compression is part of the trust boundary. Brotli was built to make the web faster, and Content-Encoding: br is now ordinary. The decoder sits in front of application logic, often in a process that also holds secrets, session state, and outbound credentials. A memory-safety bug there is not a niche parser issue. It is a network-reachable primitive in software people forgot they shipped.

The long gap between the fix landing on the Brotli main branch in February 2026 and a tagged release in October shows the other half of the problem. A commit without a release, an advisory, and a downstream rebuild does not protect anyone. Vendoring makes that worse. Node.js, Bun, Envoy, .NET, and language bindings each needed their own update, and scanners that only watch the upstream package name will miss most of them.

For defenders, the useful lesson is narrower than the nicknames. Find every place you inflate data you do not control, patch the decoder to 1.0.10, 1.1.1, or 1.2.1 or the vendor build that contains that fix, and keep a hard cap on decompressed size so the next compression bug is a rejected request instead of a crashed, or compromised, process. Federal agencies have until November 10. Everyone else should treat that date as a ceiling, not a suggestion.