Report an Incident Become a Partner Careers Contact
Book a Demo
Threat Research

Opt-In, Still Exposed: Finding The Brotli Flaw (CVE-2026-111497) Across Your .NET And Node.js Estate

Mohammad A'mir · Incident Response & Threat Intelligence Analyst 28 October 2026 8 min read
A host panel showing the .NET runtime 8.0.33 patched in green, above four applications: a web API on the shared runtime marked fixed, and a self-contained app, a container image and an app with bundled Node marked exposed in red, beside the headline "Patched host. Exposed apps."

On Sunday 25 October, Microsoft shipped out-of-band .NET updates for CVE-2026-111497, a memory corruption flaw in the Brotli decompression library that has been given the names HTTP2Shell, Node2Shell and Broccoli2Shell. The same bug was fixed in Node.js, Python's Brotli packages and Google's own library earlier in the week. Installing the update on a server is the easy part. The harder job is finding the applications that carry their own copy of the decoder, because a runtime update on the host does not reach them.

This post covers what the flaw is, which .NET and Node.js workloads are actually exposed, and how to find them with Microsoft Defender and Sentinel.

What happened

Brotli is a compression format used across the web. Browsers request it, servers send it, and HTTP clients decode it automatically. The flaw sits in Google's C decoder. When a crafted stream contains an invalid block switch, the decoder treats it as a request for more input instead of an error, and keeps appending bytes to an eight-byte internal buffer until it writes past the end. Node.js describes the result as a crash, disclosure of process memory, or remote code execution.

The timeline, as tracked on the community tracking page:

  • 21 October: fixed releases of Node.js (22.23.4, 24.22.1, 26.12.1) and Brotli (1.0.10, 1.1.1, 1.2.1).
  • 22 October: public disclosure, a published analysis demonstrating code execution against an unmodified Node.js image, and a public proof of concept.
  • 23 October: fixed Python packages (Brotli 1.2.1, brotlicffi 1.2.1.0).
  • 25 October: .NET 8.0.33, 9.0.22 and 10.0.14, plus .NET 11 RC3.

As of 27 October, no exploitation in the wild had been reported. The public proof of concept reportedly reaches code execution only on a deliberately weakened build, and crashes standard ones. That gives defenders time, but not much: the bug is well understood, and the first working exploit is a matter of effort, not discovery.

Who is affected in a .NET estate

Microsoft's advisory says the flaw "may allow an unauthenticated attacker to read or corrupt process memory", leading to information disclosure, denial of service or elevation of privilege. It applies on all platforms, but only to applications that decode Brotli through one of three routes:

  • ASP.NET Core request decompression middleware, which accepts Content-Encoding: br request bodies.
  • HttpClient automatic decompression, where AutomaticDecompression includes Brotli or is set to All.
  • The System.IO.Compression Brotli APIs, such as BrotliStream and BrotliDecoder.

Request decompression and automatic response decompression are off by default. That is good news, but it cuts both ways. Opting in is a one-line change a developer makes in code, so it rarely appears in any configuration review. Your infrastructure team cannot tell from the server which applications switched it on. .NET Framework is not affected.

Where the runtime lives decides how you patch:

  • Framework-dependent apps use the shared runtime. Update the runtime, then restart the application.
  • Self-contained apps carry their own runtime. Updating the host does nothing; they must be rebuilt and republished.
  • Containers carry their own runtime too. Rebuild from the updated base images and redeploy.

Node.js and everything else

Node.js is the clearest case. Any process that decompresses attacker-supplied Brotli through node:zlib is exposed, including Node's built-in fetch() when it calls a hostile server, and Express 5 or body-parser 2 apps that decode Brotli request bodies. There is no workaround. Lines 20, 23 and 25 are end of life and will not be fixed.

Beyond that, Python HTTP clients that have a Brotli package installed decode it automatically, and the tracking page lists vendored copies inside databases, archive tools, PDF libraries and firmware toolchains, some still unpatched. A distribution update fixes programs that link the system library, after a restart. It does not fix anything with its own copy compiled in.

A server can be fully patched and still run three vulnerable copies of the same library, inside three applications that each brought their own.

Finding it with Defender and Sentinel

The queries below are starting points to tune for your estate. Software names in Defender Vulnerability Management vary by product and platform, so check what your tenant actually reports before relying on a filter. Linux servers, build agents and containers only appear if Defender for Endpoint or Defender for Cloud covers them.

1. What Defender already knows

DeviceTvmSoftwareVulnerabilities
| where CveId == "CVE-2026-111497"
| summarize Devices = dcount(DeviceName), Examples = make_set(DeviceName, 10)
          by SoftwareVendor, SoftwareName, SoftwareVersion
| order by Devices desc

This is the fastest list, but it sees installed software, not copies bundled inside applications. Treat it as the floor, not the ceiling.

2. .NET apps loading the native compression library

The .NET Brotli implementation is native code in System.IO.Compression.Native. Any process that loads it from outside the shared runtime folder is carrying its own runtime, and must be rebuilt.

DeviceImageLoadEvents
| where Timestamp > ago(14d)
| where FileName in~ ("System.IO.Compression.Native.dll", "libSystem.IO.Compression.Native.so")
| extend Shared = FolderPath has_any (@"\dotnet\shared\", "/dotnet/shared/")
| summarize Hosts = dcount(DeviceName), LastSeen = max(Timestamp)
          by InitiatingProcessFileName, FolderPath, Shared
| order by Shared asc, Hosts desc

Loading the library does not prove the app decodes Brotli. It tells you which apps your developers need to check, and which ones a runtime update will not fix.

3. Node.js binaries and their versions

DeviceProcessEvents
| where Timestamp > ago(14d)
| where FileName in~ ("node.exe", "node")
| summarize Hosts = dcount(DeviceName), LastSeen = max(Timestamp)
          by FolderPath, ProcessVersionInfoProductVersion
| order by Hosts desc

Anything below 22.23.4, 24.22.1 or 26.12.1, or on an end-of-life line, needs updating. Look for copies inside application folders: desktop apps built on Electron and developer tools often ship their own Node runtime.

4. Unexpected crashes on web-facing hosts

Failed exploit attempts against this bug tend to crash the process. If you collect the Application event log, a cluster of faults in web workers is worth a look:

Event
| where TimeGenerated > ago(7d)
| where Source == "Application Error" and EventID == 1000
| where RenderedDescription has_any ("w3wp.exe", "dotnet.exe", "node.exe")
| summarize Crashes = count(), First = min(TimeGenerated), Last = max(TimeGenerated)
          by Computer, bin(TimeGenerated, 1h)
| where Crashes >= 3

Correlate any hits with web server or WAF logs for requests carrying Content-Encoding: br at the same time.

What to do now

  1. Patch the runtimes. .NET 8.0.33, 9.0.22 or 10.0.14; Node.js 22.23.4, 24.22.1 or 26.12.1; Python Brotli 1.2.1 or later. Restart the processes afterwards.
  2. Rebuild what carries its own copy. Self-contained .NET apps, container images and anything bundling Node. Update lock files too, or the next build reinstalls the old version.
  3. Ask developers one question: which of our services accept compressed request bodies, or call external URLs with automatic decompression on? Those go first.
  4. Restrict inbound Brotli on internet-facing services that don't need it, by rejecting Content-Encoding: br at the reverse proxy or WAF while patches roll out. This does not protect clients that fetch from hostile servers, so it is a stopgap only.
  5. Chase your vendors for products that bundle the library, using the tracking page's list as a prompt.

Microsoft's release also re-issues fixes for two October Patch Tuesday CVEs that were not fully addressed the first time, CVE-2026-70197 and CVE-2026-102870, so this update is worth taking even where Brotli is off. For the wider problem of flaws that sit inside other software, read our view on why library flaws hide from patch reports.

How a managed SOC helps

  • Exposure and detection together. We bring Defender Vulnerability Management, endpoint and server telemetry into one picture, so the list of exposed apps and the crash that might be an exploit attempt are looked at side by side.
  • Investigation at speed. CYBERSHIELD AI's Investigation Agent works each alert to a verdict, averaging 3m 30s, and our analysts take it from there, with senior analyst sign-off by default.
  • Patching that is followed through. Our vulnerability and patch management service tracks fixes to the rebuild and redeploy, not just the installer.

If you want help working out which of your applications carry the vulnerable decoder, talk to our team.

Threat ResearchCVE-2026-111497BrotliHTTP2Shell.NETASP.NET CoreNode.jsVulnerability ManagementMicrosoft Defender Vulnerability ManagementKQLThreat HuntingSupply Chain

Ready to see the agents work?

Book a demo of CYBERSHIELD AI against a real scenario.