Back to the blog
Vulnerability8 min read

Node2Shell: The Critical Brotli Flaw That Hit Node.js, .NET and Python (2026)

Node2Shell (CVE-2026-111497): a critical flaw in Google's Brotli library hits Node.js, .NET, Python and more. Who's exposed and how to fix it now.

Diego Melo, author
Diego Melo

Security researcher and founder of No Vuln

Node2Shell: The Critical Brotli Flaw That Hit Node.js, .NET and Python (2026)

If your app runs on Node.js, .NET, or any service that decompresses Brotli data from outside, update the runtime. On October 21, 2026 — in the same batch of fixes that brought php2shell to PHP — Node2Shell (CVE-2026-111497) surfaced: a critical flaw in Google's Brotli decompressor, the library that Node.js and much other software embed. The detail that makes it interesting isn't a single product: one shared library forced fixes to Node.js, .NET, PowerShell, Python, Bun and more, all in the same week. This post explains what the flaw is, who is actually exposed, how it works, and the steps to fix it.

What Node2Shell is

It's a flaw in the Brotli decompressor — technically an out-of-bounds write caused by an error return that wasn't checked. Brotli is the compression algorithm Google created and that's used across the web (it's the Content-Encoding: br your browser negotiates with servers). The problem isn't in HTTP or in Node.js itself: it's in the C code of the decompressor, which Node and dozens of other projects compile in. CISA, in fact, cataloged the flaw as the “Google Brotli Unchecked Return Value Vulnerability.”

Severity is 9.2 out of 10 on the CVSS 4.0 scale (Google's rating). The possible impact: carefully crafted Brotli data corrupts the decompressor's memory and, from there, can crash the process, leak chunks of memory, or — worst case — lead to remote code execution. Affected library versions run from 1.0.3 to 1.2.0; the fix is in 1.0.10, 1.1.1 and 1.2.1. The flaw was found by OpenAI's security team.

Why this isn't just Node.js

Here's the angle worth keeping: when a flaw lives in a shared dependency, it doesn't respect a language boundary. The same Brotli decompressor is embedded in a lot of software, which is why the week turned into a parallel patch race:

  • Node.js — fixed in 22.23.4, 24.22.1 and 26.12.1;
  • Microsoft — out-of-band update on Oct 25: .NET 8.0.33, 9.0.22 and 10.0.14 (plus .NET 11 RC3), Visual Studio 2019/2022/2026 and PowerShell 7.4/7.5/7.6;
  • Python — the Brotli (1.2.1) and brotlicffi (1.2.1.0) packages on PyPI;
  • Bun, Envoy and Istio also shipped fixed versions.

And there are still projects that, per public trackers (which call themselves incomplete), were unpatched when the news broke — DuckDB, Apache Arrow, 7-Zip variants and EDK II (firmware). Not every configuration of those projects exposes the vulnerable code, but the message is the same: look for Brotli across your stack, not just Node.

Who is exposed (and who isn't)

The good news: exposure is not automatic. For the flaw to be reached, attacker-controlled Brotli data has to reach the native decompressor. In Imperva's tests, two typical Node.js paths lead there:

  • A response your app consumes: your service makes an outbound call and decompresses a Brotli response from another server using Node's built-in fetch(). If that “other server” is hostile (or an SSRF makes your app talk to it), the data reaches the decoder.
  • The request body: apps on Express 5.0.0–5.3.0 or body-parser 2.0.0–2.3.0, with Brotli handling configured, decompress the body a client sent (Content-Encoding: br).

And the part that heads off panic: a bare Node HTTP server doesn't decode a Brotli body just by receiving it. In other words, not every Node app is exposed — but either pattern above (and they're common in APIs and integrations) is enough to be. The right question isn't “do I use Node?” but “does my app decompress Brotli from a source I don't control?”

How the flaw works

In plain terms: the Brotli decompressor keeps working after a condition that should have stopped it. An internal transition that the stream's own structure makes impossible ends up read as “I need more data,” and decoding continues from an invalid state — the moment at which it can write past the space reserved in memory. That memory corruption is what, chained together, opens the door to the rest. The upstream fix is precisely to make the decoder return a format error and pass it back to the caller, instead of pressing on. (We won't publish exploitation details here.)

Is it being exploited?

It's worth being honest about the stage, without hype or minimizing. Imperva demonstrated remote code execution in a proof of concept against the official Node.js 24.22.0 image (the same payload was rejected on the patched 24.22.1) — so it's not just theory, though the exploit doesn't work on every attempt and wasn't published. In parallel, some researchers argue that in many scenarios the practical effect stays at denial of service. The decisive point for decision-makers: on October 27, 2026 CISA added CVE-2026-111497 to its KEV catalog (vulnerabilities with confirmed exploitation), with a November 10 deadline for U.S. federal agencies to fix it. Once something lands in KEV, the conversation stops being “if” and becomes “when” — the time to update is now.

How to fix it now

  1. Find where Brotli lives. Don't look only at Node: map .NET services, PowerShell scripts, Python dependencies (Brotli/brotlicffi) and proxies like Envoy/Istio. The question is per runtime and per library, not per app.
  2. Update the runtime. On Node.js, to a fixed version (released Oct 21, 2026):
    Node.js 22.x  →  22.23.4
    Node.js 24.x  →  24.22.1
    Node.js 26.x  →  26.12.1
    On .NET, apply Microsoft's out-of-band update (Oct 25); on Python, bump the Brotli packages to 1.2.1 / 1.2.1.0.
  3. Restart the process and rebuild images. This step is easy to forget: a running process keeps using the old (vulnerable) Brotli code already loaded in memory. Updating the package isn't enough without restarting the service — and, in containers, without rebuilding the image on the already-fixed base.
  4. On an unsupported line? Node.js 20.x reached end of life in April 2026 and got no official fix — if you're still on it, migrate to a supported line rather than wait for a patch.
  5. WAF as a temporary layer. WAF rules for the known vector help you buy time (Imperva itself published protections), but they don't close the flaw — the patch is the only definitive fix.

The takeaway: your attack surface includes your dependencies

Node2Shell is a reminder of an uncomfortable truth: you don't just run the code you wrote. You run a stack of third-party libraries compiled in, and a flaw in one of them becomes your flaw — sometimes in places you'd never associate with that dependency (who'd expect a compression flaw to show up in PowerShell and .NET at the same time?). It's the same kind of supply-chain risk we saw in the ConnectWise attack, just via the embedded dependency rather than the SaaS vendor.

That's why an honest dependency inventory (SBOM) and a pentest that tests the app the way a real adversary would — including the points where it processes outside data — are worth more than trusting that “everything's up to date.” If you want to map where your platform processes untrusted input and where that becomes risk, talk to a researcher. And, more broadly, a periodic pentest finds those doors before they make headlines.

Sources and analysis: NVD CVE-2026-111497, CISA KEV, Imperva, SecurityWeek and Akamai. Version numbers and exploitation status may be revised as the investigation advances — always confirm against the official advisory for your runtime and distribution.

Share

WhatsAppLinkedInX

Next step

Want to apply this to your system?

No Vuln runs in-depth penetration tests with the same methodology described in this article. Request a proposal: mutual NDA within 24h, scope defined on a technical call.