$RodHat_/search
MOTD

CVE-2026-111497 is not a Node.js bug: HTTP2Shell spreads to Python, curl, and your build toolchain

Published by

This article may contain Amazon affiliate links. I may earn a commission if you buy through them. Disclosure.

Photo by Erick Angeles
Photo: Erick Angeles / Unsplash

Six days ago, when Node.js shipped their October security releases, CVE-2026-111497 was called Node2Shell and treated as a Node.js runtime problem. That framing did not survive the week.

The bug lives in Google’s upstream C Brotli decoder, versions 1.0.3 through 1.2.0. A malformed compressed stream pushes the decoder into a state where it believes more data is still expected after the stream has ended, and it writes attacker-controlled bytes across a memory boundary. Google’s C library is what Node.js vendors. It is also what the Python Brotli package and brotlicffi compile directly. Researchers at Aikido had a working PoC against Python 3.13 with requests installed by late October 23. The name changed to HTTP2Shell because that is what the scope actually is: any process that negotiates Content-Encoding: br and then decompresses the response.

The Python exposure path is worth spelling out because it is not obvious. If Brotli or brotlicffi is installed in your environment, then requests, urllib3, aiohttp, and httpx will all advertise Brotli support in their Accept-Encoding header automatically. You do not opt in to compression. The client broadcasts the capability and the server obliges. If you are making HTTP requests against anything outside your control — third-party APIs, RSS feeds, user-supplied URLs, webhook callbacks — a server that sends a crafted Content-Encoding: br response now has a path to your process heap.

Checking exposure:

# Python: want Brotli >= 1.2.1, brotlicffi >= 1.2.1.0
pip show Brotli brotlicffi 2>/dev/null | grep -E '^(Name|Version)'

# Node.js: want >= 22.23.4, 24.22.1, or 26.12.1
node --version

# curl: want libbrotlidec >= 1.1.1
curl --version | grep -i brotli

If pip list | grep -i brotli shows anything below 1.2.1, that host is exposed to any attacker who can influence an HTTP response it receives. That is a wider attack surface than “we run Node,” which is why the rename matters beyond marketing.

Brotli is an optional HTTP client dependency, which means it is invisible in a lot of environments until you go looking. It does not show up in your direct requirements.txt unless you explicitly asked for Brotli support; it shows up in transitive installs from anything that can speed up HTTP responses. pip list is the correct audit tool, not a code search for import brotli.

The fixed versions: Brotli 1.0.10, 1.1.1, and 1.2.1 from Google; Python Brotli 1.2.1; brotlicffi 1.2.1.0; Node.js 22.23.4, 24.22.1, 26.12.1; Bun 1.4.4. No confirmed exploitation in the wild as of today, and it is not in CISA’s KEV catalog yet. That is the window. Heap corruption in a decompressor that processes attacker-controlled network data has a track record of being less theoretical than it looks at disclosure.

CVSS 4.0 is 9.2. If you were waiting for something with a big number and a logo, this one already has a name. The name is just worse than the CVE deserved.

If your environment runs into the LiteLLM supply chain mess from two days ago or anything else with broad Python HTTP client use, Brotli is worth auditing in the same pass. The kernel-security pattern this week has been one thing after another where the “obvious” attack surface was not actually the scope.

Sources

  1. Python packages vulnerable to Node2Shell/Brotli CVE-2026-111497 (Aikido Security)
  2. HTTP2Shell (CVE-2026-111497): The Brotli RCE Hitting Node.js, Python and More (Strobes Security)