Logo
Overview

Node2Shell: Brotli Decoder RCE in Node.js (CVE-2026-111497)

Node2Shell, also called HTTP2Shell, is an out-of-bounds write in the Brotli decoder affecting Node.js, Python, Bun, Envoy and .NET. Who is affected and the fixed versions.

6 min read

Status: Patched
Severity: Critical, CVSS v4.0 9.2 (Google, the CVE’s assigner) · Node.js rates it High

Overview

Node2Shell is CVE-2026-111497, an out-of-bounds write in Google’s Brotli decoder. Crafted Brotli-compressed data can crash a process, disclose process memory or, in some setups, run code. It affects Node.js, Python’s Brotli packages, Bun, Envoy, .NET and other software that bundles the decoder. Fixes shipped from 21 October 2026. Update, rebuild and restart.

Why So Many Names?

  • Node2Shell: Imperva’s name for the Node.js exposure, where the bug first drew broad attention.
  • HTTP2Shell: a later name for the wider impact. Despite the name, this is not an HTTP/2 bug, or necessarily an HTTP bug. Any attacker-controlled Brotli stream that reaches an affected decoder can trigger it.
  • Broccoli2Shell: the name used by an independent tracking site that lists affected software.

All three are CVE-2026-111497. Patching for one patches for all of them.

Am I Affected?

  • Google Brotli: 1.0.x from 1.0.3 before 1.0.10, plus 1.1.0 and 1.2.0, on all platforms.
  • Node.js: 22.x, 24.x and 26.x before the fixed releases. Node.js says end-of-life versions are always affected when a security release ships; that includes 20.x, 23.x and 25.x.
  • Python: the Brotli package from 1.0.3 up to 1.2.1, and brotlicffi from 1.0.3 up to 1.2.1.0. Clients such as urllib3, Requests, HTTPX and aiohttp decode Brotli responses automatically when one of these packages is installed, even if your code never imports it.
  • Bun: 1.0.21 up to 1.4.4.
  • Envoy: deployments with the Brotli decompressor configured.
  • .NET: .NET 8, 9 and 10 runtimes before the fixed releases, and .NET 11 previews. It is only reachable through ASP.NET Core request decompression with the br provider, HttpClient automatic Brotli decompression, or direct use of BrotliStream or BrotliDecoder, none of which is on by default. .NET Framework is not affected.
  • Other software: anything that bundles or links an affected Brotli, such as curl builds that decode Brotli responses (--compressed) using an affected libbrotli. Check each vendor’s advisory and your OS packages.

When Is It Reachable?

An attacker must get a crafted Brotli stream decoded by a vulnerable copy. Common routes:

  • Compressed request bodies: services that decompress incoming bodies sent with Content-Encoding: br. Imperva confirmed this path through Express 5.0.0–5.3.0 and body-parser 2.0.0–2.3.0 with the raw() and json() parsers. Running Express alone does not mean you are exposed, and a bare Node.js HTTP server does not decode incoming Brotli bodies.
  • Compressed responses: clients that decode Brotli responses from servers they don’t control, for example webhooks or URL previews. Imperva confirmed this path through Node.js’s built-in fetch().
  • Direct decoding: code that passes untrusted data, including uploaded or imported files, to node:zlib’s Brotli functions or equivalent APIs in other languages.

What to Do

  1. Find every copy of Brotli: Node.js runtimes (including inside container images), Python environments, .NET apps, and other runtimes, proxies and tools that bundle it.
  2. Update Node.js to 22.23.4, 24.22.1 or 26.12.1, or later. Move off end-of-life Node.js lines.
  3. Update Python’s Brotli to 1.2.1 and brotlicffi to 1.2.1.0, then regenerate lockfiles.
  4. Update the system Brotli library to 1.2.1, or to 1.1.1 or 1.0.10 on those branches. Distribution packages may backport the fix without changing the version number, so follow your distribution’s advisory.
  5. Update everything else that bundles Brotli, including Bun, Envoy and .NET.
  6. Rebuild, redeploy and restart. Running processes keep the old decoder until they restart. Rebuild Bun bun build --compile executables, republish .NET NativeAOT apps, and rebuild container images.
  7. If you can’t update straight away: Node.js says there is no workaround. As a stopgap, some researchers suggest rejecting requests with Content-Encoding: br at your proxy or middleware. This does not protect responses your services fetch, so prioritise updating services that call untrusted servers. For .NET, Microsoft suggests removing the br provider from request decompression and Brotli from HttpClient automatic decompression.

Fixed Versions

ComponentFixed in
Google Brotli1.2.1, 1.1.1, 1.0.10
Node.js26.12.1, 24.22.1, 22.23.4
Python Brotli1.2.1
brotlicffi1.2.1.0
Bun1.4.4
Envoy1.40.0, 1.39.3, 1.38.6
Envoy (older)1.37.8, 1.36.12
.NET10.0.14, 9.0.22, 8.0.33
.NET 1111.0.0-rc.3

Timeline

DateEvent
2026-02-27Fix lands in Brotli’s source, not marked as a security fix
2026-10-21Brotli 1.0.10, 1.1.1 and 1.2.1 released
2026-10-21Node.js 22.23.4, 24.22.1 and 26.12.1 released
2026-10-22Imperva reports code execution on Node.js 24.22.0
2026-10-22GitHub advisory for Python Brotli and brotlicffi; fixes on PyPI
2026-10-23Bun and Envoy publish advisories
2026-10-25Microsoft publishes the .NET advisory

The fix (commit 0ed4268, “Detect and report invalid stream earlier”) was public in Brotli’s source from 27 February, but nothing marked it as a security fix and no release shipped it until October. Software built from release tarballs or older vendored copies stayed affected until then.

Technical Summary

  • The bug: a Brotli stream can tell the decoder to switch between block types. A crafted stream asks for a switch after declaring only one block type. In the vulnerable code, DecodeBlockTypeAndLength() returned the same result for this format error as for “not enough input yet”, so the streaming decoder waited for more data (CWE-252, unchecked return value).
  • The corruption: as more input arrived, the decoder kept appending it to an eight-byte internal buffer and wrote past its end into neighbouring decoder state (CWE-787, out-of-bounds write).
  • The impact: depending on what is overwritten, a crash, disclosure of process memory, or code execution in the process. Imperva reached code execution on the official Node.js 24.22.0 Linux arm64 image, which took multiple attempts. Imperva has not released an exploit, and public crash demonstrations are not the same as a reliable RCE exploit.
  • The fix: the decoder now returns a specific error, BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH, for an impossible block switch and stops instead of buffering. Patched Node.js rejects Imperva’s inputs and keeps running.
  • Severity: CVSS v4.0 9.2 (AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N). “Attack requirements: present” reflects that the target must decode Brotli from an attacker-influenced source. Microsoft scores the .NET exposure CVSS v3.1 8.1.

Update Log

  • 26 October 2026: Initial publication. Status: patched.

References

Hacktron finds and fixes real security vulnerabilities before they ship to production.