Industry Trends & Events

Node2Shell (CVE-2026-111497): Scoping and Remediating Brotli Exposure

by David Allen, CTO//

Talk to a Brinqa ExpertTalk to a Brinqa Expert

On October 21, 2026, Node.js shipped fixes for CVE-2026-111497, a memory corruption bug in the Brotli decoder built into its runtime. Researchers call it Node2Shell, and Google rates it 9.2 under CVSS v4.0, while Node.js classifies it as High.

Brotli is a compression format Google created to shrink data in transit. If an attacker gets a crafted Brotli stream decoded by a vulnerable copy, the resulting memory corruption can crash the process, leak memory or let the attacker run their own code. Many projects bundle their own copy of Brotli, so Node.js, Python, .NET, Bun, Envoy, and others each needed a separate fix. On October 27, CISA placed it in the KEV catalog.

How Node2Shell works

Brotli data is split into blocks, and the stream tells the decoder when to switch block types. A malicious stream can demand a switch that is impossible. Older decoders misread that as a pause in the data and kept piling incoming bytes into an eight-byte holding area until they spilled past it. Google Brotli 1.0.3 through 1.2.0 is affected, and 1.2.1, 1.1.1 and 1.0.10 contain the correction.

The fix landed in Brotli's public code on February 27, 2026, but nobody flagged it as a security change, and no release carried it until October. OpenAI's Codex Security team reported the flaw, making Node2Shell the second AI-assisted discovery this month after PHP2Shell.

Node2Shell timeline

  • February 27, 2026: Google merges the fix quietly, with no security label.
  • October 21: Node.js discloses and ships 22.23.4, 24.22.1 and 26.12.1; Google releases fixed Brotli versions.
  • October 22: Python Brotli and brotlicffi are fixed (GitHub advisory), and Imperva runs attacker code on a stock Node.js build.
  • October 25: .NET updates arrive from Microsoft outside the normal patch cycle.
  • October 26: ELLIO sensors record live exploit attempts.
  • October 27: The CVE enters CISA's KEV catalog.

Exploitation status

Researchers have published working exploit code, and Imperva demonstrated that an unmodified Node.js 24.22.0 build for Linux arm64 can be made to run attacker code, though it took several tries. On October 26, ELLIO reported live exploit traffic against its sensors, sent from an address with a record of PHP2Shell attacks. CISA added the CVE to the KEV catalog the next day.

How reliably the exploit works depends on the platform and build. Reachable systems come first, and vendor advisories will carry any status changes.

Where Brotli hides in your environment, and when it matters

Finding every copy

Upgrading Node.js patches only the decoder inside Node.js. The Brotli package in a Python environment, the runtime inside a self-contained .NET app and the decoder compiled into a proxy each need their own fix. Python adds a twist: if the Brotli package is present, popular HTTP clients such as urllib3, Requests, HTTPX and aiohttp use it on their own, whether or not the application ever calls it.

Old container images carry the flawed decoder forward until someone rebuilds them. Distribution packages can carry the fix under an unchanged version number, so a version check alone can mislead. Node.js 20.x, 23.x and 25.x are past end of life and stay unpatched upstream. A check that looks only at Node.js versions will miss many of these copies.

Deciding what is reachable

A vulnerable decoder matters most where outside data can reach it, and that’s what should set the order of work. Imperva’s research identified two common paths:

  • Inbound request bodies. Express 5 and body-parser 2.x unpack requests sent with Content-Encoding: br before application code runs. Internet-facing Express APIs can be exposed even if their developers never chose to use Brotli.
  • Outbound responses. Services that pull content from third-party servers, such as webhook senders and link previewers, can receive a malicious response. Node.js’s built-in fetch() unpacks it automatically.

In .NET, these paths are off by default, and .NET Framework is not affected.

How to respond to Node2Shell

  1. Build your inventory. Pull together host, dependency, container and cloud findings for Node.js, Python, .NET, Bun, Envoy, Istio and operating system Brotli packages. Keep a list of systems still unconfirmed.
  2. Rank by reachability. Internet-facing Express 5 APIs go first, followed by services that fetch content from servers outside of your control.
  3. Name an owner for each fix. Application teams, platform teams, and vendors each hold different pieces. For hosted and managed services, ask for a patch date from the provider.
  4. Update, rebuild and restart. Install the fixed release from the table below, refresh lockfiles and rebuild any image or self-contained app. Running processes hold the old code until they restart.
  5. Bridge where a patch has to wait. The Node.js advisory lists no workaround. Dropping requests that carry Content-Encoding: br at a proxy or WAF cuts inbound exposure, though responses your services fetch remain unprotected.
  6. Verify and monitor. Confirm each fix with a fresh scan, document any exception, and alert on Node.js or Python processes that spawn a shell.

Node2Shell fixed versions by component

ComponentFixed versions

Google Brotli

1.2.1, 1.1.1, 1.0.10

Node.js

26.12.1, 24.22.1, 22.23.4

Python Brotli / brotlicffi

1.2.1 / 1.2.1.0

.NET

10.0.14, 9.0.22, 8.0.33

Bun

1.4.4

Fixed versions come from the advisories for Node.js, Python (GitHub advisory), .NET (Microsoft), Bun and Envoy. For operating system packages, follow your Linux distribution's advisory.

How Brinqa supports your Node2Shell response

Finding Node2Shell exposure means joining evidence that lives in separate tools. A container scanner flags the image, a dependency scanner flags the Python package, an infrastructure scanner flags the host, and a cloud inventory knows what faces the internet. Brinqa pulls those signals together.

  • Reach: The CyberRisk Graph™ correlates findings from more than 300 security and IT tools Brinqa can connect to with your asset records, so teams see each CVE-2026-111497 detection alongside whether that asset is internet-facing.
  • Ownership: The AI Attribution Agent points each affected asset to a responsible owner, and business context sets the order of work.
  • Verification: SmartFlows assigns each finding to the right team and holds it open until connected tools report the exposure resolved.

Coverage follows your detection sources. When the tools you connect add CVE-2026-111497 checks, those results flow into Brinqa with the rest of your data.

What we can learn from Node2Shell

A single change to Google's code turned into separate patches for runtimes, packages, proxies and operating systems, and each one has its own owner. Teams move through disclosures like this faster when they can see where a component runs, which copies outside data can reach, and who is responsible for each.

Talk to Brinqa about mapping your Node2Shell exposure and seeing it through to a verified fix.

FAQs

Node2Shell is a memory corruption flaw in the Brotli decoder. A crafted Brotli stream decoded by a vulnerable copy can crash the process, leak memory or let an attacker run their own code. Google rates it 9.2 under CVSS v4.0, and Node.js classifies it as High.

Yes. Researchers have published working exploit code, and Imperva ran attacker code on a stock Node.js build. On October 26, ELLIO recorded live exploit attempts against its sensors. CISA added CVE-2026-111497 to the KEV catalog on October 27.

Google Brotli 1.0.3 through 1.2.0 is affected. Many projects bundle their own copy of Brotli, so Node.js, Python Brotli and brotlicffi, .NET, Bun, Envoy and operating system Brotli packages each needed a separate fix. Node.js 20.x, 23.x and 25.x are past end of life and remain unpatched. .NET Framework is not affected.

No. Upgrading Node.js patches only the decoder inside Node.js. Python packages, self-contained .NET apps, proxies and old container images each need their own fix. Distribution packages can carry the fix under an unchanged version number, so a version check alone can mislead.

Start with systems that outside data can reach. Internet-facing Express 5 APIs go first, because Express 5 and body-parser 2.x unpack Brotli request bodies before application code runs. Next come services that fetch content from outside servers, such as webhook senders and link previewers.

The Node.js advisory lists no workaround. Dropping requests that carry Content-Encoding: br at a proxy or WAF cuts inbound exposure. Responses your services fetch from outside servers remain unprotected.

D
David Allen
Chief Technology Officer
David Allen is Chief Technology Officer at Brinqa, where he leads the company’s engineering, cloud operations, and information security functions. He is responsible for delivering a scalable, reliable, and secure platform, and for executing on Brinqa’s technology vision in alignment with business objectives.
See all of David's postsArrow Right

Ready to Unify Your Cyber Risk Lifecycle?

Get a DemoArrow RightGet a DemoArrow Right