Skip to main content
Return to TrendAI™ Güvenlik Blogu
Vulnerabilities and exploits

Brotli Flaw Behind 'Node2Shell': What to Patch and Where It Hides

NetworkWebExploits & Zero-Days

Key Takeaways

  • A flaw in the Brotli decompression library (CVE-2026-111497, CVSS 4.0 score 9.2, Critical) lets crafted compressed data corrupt memory. Brotli versions 1.0.3 to 1.0.9, 1.1.0 and 1.2.0 are affected, and fixed releases are out for Brotli itself and for Node.js, Bun, Envoy, Istio, .NET, and Python packages.
  • The Brotli flaw works in both directions: An unpatched server that accepts compressed requests can be attacked by a malicious client, and an unpatched client that accepts compressed responses can be attacked by a malicious server.
  • Public proof-of-concept code appeared on October 22. Imperva (October 22, arm64) and ELLIO (October 25, x86-64) each demonstrated code execution on official Node.js 24.22.0 builds in a lab, through a request body and, in Imperva's tests, a fetched response, though not on every attempt. The Cybersecurity and Infrastructure Security Agency (CISA) added the flaw to its Known Exploited Vulnerabilities (KEV) catalog on October 27. ELLIO reported recording an exploit request on October 26; ELLIO’s own testing suggests that payload did not work. No confirmed compromise of a victim has been publicly reported as of October 28.
  • Brotli is bundled inside runtimes, proxies, container images, and other software, often where no dependency list shows it, so patching the obvious places is not enough.
  • If you cannot patch right away, turn off Brotli decompression for data you do not control.
  • TrendAI™ customers can visit our knowledge base entry for information on available solutions. Details are in "How TrendAI™ can help" below.

What happened

On October 21, 2026, Node.js released security updates that included a fix for an out-of-bounds write in its bundled Brotli decoder. According to Node.js, an invalid block switch in the compressed stream was treated as a temporary need for more input instead of a format error, so the decoder kept adding attacker-supplied bytes to a small internal buffer and wrote past its end. Google's CVE record describes the result as memory corruption that can disclose sensitive memory, crash the process or potentially execute arbitrary code. Google rates it 9.2 (Critical) under CVSS 4.0; Node.js rates it High. Microsoft rates it 8.1 (CVSS 3.1) for .NET. The CVE record classifies it as CWE-787 (out-of-bounds write) with a CVSS 4.0 vector of AV:N/AC:L/AT:P/PR:N/UI:N: it can be reached over the network with no login and no user action, but only where the target decodes Brotli.

Google released fixed Brotli versions 1.0.10, 1.1.1, and 1.2.1 on October 21. Envoy and Istio shipped fixed releases earlier in October without naming the flaw, and Bun followed with its own fix. OpenAI said its Codex Security team had found the flaw and reported it to the Brotli maintainers and downstream projects. The Node.js advisory credits Khai Tran and Sylvie Mayer of OpenAI Codex Security.

Public proof-of-concept code appeared on October 22; its author reported code execution only against a deliberately weakened build. Since then, the risk has become more concrete. On October 22, Imperva Red Team reported running code on the official Node.js 24.22.0 image for Linux arm64, with no debugger or instrumented binary. It reproduced the result by two routes: a Brotli-compressed request body decoded by Express 5 (body-parser 2.x), and a Brotli-compressed response read by Node.js’s built-in fetch(). Execution took multiple attempts. Imperva’s results cover its tested setups, and it did not test every Node.js build or application. Node.js 24.22.1 rejects the same input. 

On October 25, ELLIO reported its own code execution on x86-64 against official, unmodified Node.js 24.22.0 builds with default settings, through a plain node:http server that decompresses with zlib, the official node:24.22.0-slim container image, Express 5.3.0, and Koa 3. Its exploit was tied to one build: the same offsets produced nothing against Node.js 22.23.3 or 26.12.0 in 10,000 attempts, and most lab attempts crashed the worker process rather than returning a shell.

On October 26, ELLIO reported recording an exploit request, a Brotli-compressed body of about 23 MB, against Node.js 24.22.0 on x86-64 from a single source IP. The request reused public proof-of-concept code with an original final stage that ELLIO’s testing found did not work. On October 27, the Cybersecurity and Infrastructure Security Agency (CISA) added the vulnerability to its KEV catalog, with a remediation deadline of November 10 for US federal civilian agencies. As of October 28, TrendAI™ has not observed a confirmed successful compromise in its telemetry. No confirmed compromise of a victim has been publicly reported as well.

The flaw has picked up several nicknames, including "Node2Shell" and "HTTP2Shell." They all refer to CVE-2026-111497.

Who is affected

Any software that passes attacker-controlled data to an unpatched Brotli decoder could be exposed to:

  • Web servers and APIs that accept Content-Encoding: br request bodies, including Node.js and Bun applications. Imperva reproduced the attack with Express 5.0.0 and 5.3.0 and body-parser 2.0.0, 2.0.1, and 2.3.0, and did not test every release in between. ELLIO also reproduced it with Express 5.3.0 and with Koa 3 and @koa/bodyparser 6. A Node.js HTTP server is exposed only if the application or a library decompresses Brotli bodies, but the vulnerable code is in the Node.js runtime, so updating Express or body-parser does not fix it.
  • Clients and background jobs that fetch content from servers as they do not control and decompress it automatically. In Python, urllib3 (and therefore requests), httpx, aiohttp and Scrapy load the Brotli or brotlicffi package automatically when it is installed, so an application can be exposed without importing it. Code execution has been shown on Node.js but has not been demonstrated in the Python packages, which compile the same decoder code.
  • Proxies and service meshes such as Envoy and Istio, configured to decompress Brotli.
  • Anything that processes Brotli-compressed files from outside sources.

Many organizations will not know they run Brotli at all, because it arrives inside a runtime, a container base image, or a proxy rather than as a direct dependency. Dependency scans run in the first days after disclosure may also have missed it: the main vulnerability databases did not list the Python packages at first, so tools such as pip-audit reported nothing. A rescan is recommended, as they are now covered (GitHub advisory GHSA-9v8h-qqgm-4m35.) 

Security researchers have also reported bundled copies in other software, including .NET, PHP, and Ruby builds, databases and archive tools. Microsoft shipped fixes for .NET 8, 9, 10 and 11 on October 25 (8.0.33, 9.0.22, 10.0.14 and 11 RC3). .NET Framework is not affected. Applications are exposed only if they use Brotli decompression, such as ASP.NET Core request decompression or HttpClient automatic decompression. PHP released updated Windows builds bundling Brotli 1.2.1 on October 26 (8.2.35-1, 8.3.36-1, 8.4.27-1 and 8.5.12-1); PHP source releases are unchanged. The PHP brotli extension is fixed in 0.21.1.

Project Fixed versions
Node.js 22.23.4, 24.22.1, 26.12.1
Bun 1.4.4
Envoy 1.40.0, 1.39.3, 1.38.6, 1.37.8, 1.36.12
Istio 1.29.9, 1.30.6, 1.31.2
Brotli (upstream C library) 1.0.10, 1.1.1, 1.2.1
Python Brotli package 1.2.1
Python brotlicffi package 1.2.1.0
.NET 8.0.33, 9.0.22, 10.0.14, 11 RC3
PHP for Windows builds 8.2.35-1, 8.3.36-1, 8.4.27-1, 8.5.12-1
PHP brotli extension 0.21.1
Table 1. Fixed versions by project

End-of-life Node.js lines (18.x, 20.x, 23.x, and 25.x) will not receive a fix. Istio 1.29 reached end of support on October 15, but 1.29.9 includes the fix.

Why this matters

The vulnerable code is not something most teams chose or track. It sits in front of everything else and can be reached by anyone who can send a request or serve a response. A fix that was already in Brotli’s source in February (committed February 27) had no release and no advisory, so most downstream projects did not pick it up for about eight months. With public code, a lab demonstration, a recorded exploit attempt and a KEV listing, that gap has already closed.

What organizations should do now

  1. Find where Brotli runs. Inventory Node.js and Bun versions across servers, functions, build agents, and container images; check Envoy and Istio versions and whether Brotli decompression is enabled; check Python environments for the Brotli and brotlicffi packages. Include developer tools and command-line tools that bundle Node.js. On Windows, include PHP builds and .NET applications that use ASP.NET Core request decompression or HttpClient automatic decompression. Software bills of materials and container image scans will find some copies, not all.
  2. Patch and redeploy. Update to a fixed release, rebuild container images and bundled executables, and restart every service, worker, and replica still running the old build. Move off end-of-life Node.js lines.
  3. Turn off Brotli decoding of untrusted data until patched. Reject requests with Content-Encoding: br before any proxy or body parser decompresses them, disable Brotli decompressor filters in Envoy and Istio for requests and responses, and stop HTTP clients from decompressing Brotli automatically. A disabled Envoy or Istio filter forwards compressed bytes unchanged, so any downstream service that decodes Brotli stays exposed. Removing br from Accept-Encoding alone does not stop a server from sending it. Gzip and deflate can stay on.
  4. Do not rely on content delivery network (CDN) or web application firewall (WAF) settings alone. Turning off Brotli response compression on a CDN does not stop request or client-side decompression, and size limits or WAF rules do not cover every decoding path.
  5. Be careful with "checkers." Treat proof-of-concept code, scanners and checkers for this flaw from unknown sources as untrusted, and run them only in an isolated lab.
  6. Watch for signs of attack. Treat these as triage leads rather than confirmed compromise: unexpected crashes, SIGSEGV signals, or restart loops in Node.js, Bun, Envoy or Istio processes, particularly right after handling a compressed request or response; unusual Content-Encoding: br traffic patterns or decoder failures following outbound HTTP fetches; unusually large Brotli-compressed request bodies (the recorded exploit request was about 23 MB); and unexpected child processes spawned from web-facing services. Patched Node.js builds reject the exploit input with a 400 response and the error code ERR__ERROR_FORMAT_BLOCK_SWITCH, so that error in application logs after patching points to an attempt worth reviewing. ELLIO has published a source IP address (94.154.43.7) and payload hash (SHA-256 7fcbdaaecd4419e2930927844f3b772668204737a4e7602a2290c991c93c5c4b), and has reported a scanner using the user agent node2shell-check/1.0 from AS44620. These are single-event indicators, not general detection guidance.

How TrendAI™ can help

Patching is the fix. These capabilities help teams find exposed systems, add a layer of protection while updates roll out, and look for signs the flaw was used. Rule names and details are in TrendAI™ knowledge base entry KA-0024830 (https://success.trendmicro.com/en-US/solution/KA-0024830).

  • See where you're exposed. TrendAI Vision One™ Cyber Risk Exposure Management (CREM) flags assets running affected versions in its Exposure Overview. It assigns each asset a criticality level, so teams can patch the internet-facing services that matter most first.
  • Add a network and host layer, with limits. TrendAI Vision One™ TippingPoint™ filter 48101, TrendAI Vision One™ Network Detection and Response (NDR) rule 6040, and intrusion prevention rule 1012761 for TrendAI Vision One™ Endpoint Security, including Server and Workload Protection, and TrendAI™ Deep Security look for exploit traffic. None of them decompress Brotli, so they inspect only the compressed bytes. Treat them as a supplement while systems are patched, not a substitute.
  • Look for signs of compromise. TrendAI Vision One™ raises Observed Attack Techniques when a Node.js process launches a command shell or makes an unexpected outbound connection, and TrendAI Vision One™ Container Security alerts on suspicious child processes and outbound connections from Node.js in containers. These match the post-exploitation behavior in "Watch for signs of attack" above.
  • Block known attack infrastructure. TrendAI™ Web Reputation Services blocks the attacker IP address reported for this activity.
  • Hunt in your own environment. TrendAI Vision One™ Threat Intelligence has an entry for this vulnerability with background and hunting guidance. Teams can also use XDR Data Explorer in TrendAI Vision One™ Agentic SIEM and XDR to search endpoint process activity for web-facing Node.js processes launching shells or download tools.
  • Hand it off. For teams without the capacity to run this themselves, TrendAI Vision One™ Services – Managed Detection and Response (MDR) provides 24/7 detection, investigation and response by TrendAI™ analysts. Organizations that want to know whether they were targeted can request a TrendAI™ compromise assessment, and those who believe they have been breached should contact TrendAI™ incident response.

TrendAI™ customers with questions can contact their account representative. Others seeking guidance can contact us at https://www.trendaisecurity.com/en-us/contact or email incident_response@trendmicro.com.