< back to blog

Node2Shell (CVE-2026-111497): Detecting the Node.js Brotli RCE

Sysdig Threat Research Team
Node2Shell (CVE-2026-111497): Detecting the Node.js Brotli RCE
Published by:
Sysdig Threat Research Team
Node2Shell (CVE-2026-111497): Detecting the Node.js Brotli RCE
Published:
October 24, 2026
falco feeds by sysdig

Falco Feeds extends the power of Falco by giving open source-focused companies access to expert-written rules that are continuously updated as new threats are discovered.

learn more
Green background with a circular icon on the left and three bullet points listing: Automatically detect threats, Eliminate rule maintenance, Stay compliant, with three black and white cursor arrows pointing at the text.

A malformed compressed stream, an ignored error, and a write past the end of a buffer. On October 21, 2026, Node.js shipped fixes for an out-of-bounds write in the Brotli decoder it bundles, versions 22.23.4, 24.22.1, and 26.12.1. One day later, on October 22, Imperva reported running code on the official Node.js 24.22.0 Docker image for Linux arm64. The vulnerability, now tracked as CVE-2026-111497, received a CVSS v4.0 base score of 9.2 (Critical) and has been widely referred to as Node2Shell. 

As of October 23, no confirmed in-the-wild exploitation has been reported, and Node2Shell has not been added to CISA’s Known Exploited Vulnerabilities (KEV) catalog. However, public proof-of-concept (PoC) code has been tested, and the gap between patch and PoC was about a day. Security teams should work to uncover all instances where their Node.js services decode Brotli data they don’t control, and begin by patching those first.

The Sysdig Threat Research Team (TRT) analyzed public Node2Shell research to help defenders understand who is reachable, what has been demonstrated versus claimed, what runtime visibility can detect, and what they can do until their organization can begin to patch.

Timeline

Date

Event

Oct. 14, 2026

Node.js pre-announces the release, naming the affected lines and a top severity of high

Oct. 21, 2026, 10:38 UTC

Node.js publishes v22.23.4, v24.22.1, and v26.12.1

Oct. 21, 2026, 15:47 UTC

The first public GitHub repository for the CVE appears, about five hours after the fixes ship

Oct. 21, 2026, ~19:27 UTC

The Brotli project publishes 1.0.10, 1.1.1, and 1.2.1, each listing CVE-2026-111497

Oct. 22, 2026

Google’s CVE record is published with a 9.2 score on CVSS v4.0

Oct. 22, 2026

Imperva publishes research showing code execution on Node.js 24.22.0

Affected Node.js versions

The bug itself is in Brotli, not within Node.js code. Node.js bundles its own copy, so fixing it means updating the runtime itself.

The Node.js advisory rates the vulnerability as high severity. Google scores it as a critical severity vulnerability, at 9.2 on CVSS v4.0. However, severity may depend on exposure, which is determined by whether your code reaches the decoder.

Node.js version

End of life

Fixed version

26.x

Apr. 30, 2029

26.12.1

24.x

Apr. 30, 2028

24.22.1

22.x

Apr. 30, 2027

22.23.4

25.x

Jun. 1, 2026 (ended)

No fix

20.x

Apr. 30, 2026 (ended)

No fix

Node.js states that end-of-life versions are always affected by security releases. Organizations running Node.js 25, 20, or older should treat those hosts as vulnerable, with no further patches coming. 

Distribution packages need their own check. Debian’s tracker, read on October 23, lists nodejs 18.20.4 in bookworm, 20.19.2 in trixie, 24.21.0 in forky, and 24.22.0 in sid as vulnerable, and notes that Debian’s nodejs uses the system Brotli library. In that case, the fix lands in the library, not just the runtime. 

Debian’s Brotli package is also vulnerable in every release the tracker lists, and the tracker shows no fixed version for any release. The tracker also shows both brotli and nodejs as unfixed in Debian’s development branch unstable. As of October 23, there is no patched Debian package for either component. Debian rates the nodejs entry as unimportant urgency, which differs from the high rating assigned by Node.js, though the tracker doesn’t state why.

The CVE record places the root bug in Google’s Brotli library 1.0.3 through 1.2.0, fixed in 1.0.10, 1.1.1, and 1.2.1. Any other software that bundles a Brotli build in that range is worth further analysis or vendor inquiry. 

But the impact isn’t limited to Debian. Packages for Ubuntu, Fedora, RHEL, and Alpine may also use the system Brotli library instead of the bundled copy. Therefore, the fix arrives through the distribution’s Brotli package, and a Node.js version number won’t indicate whether a given instance is patched.

According to Aikido, Bun is also affected. All versions 1.4.3 and earlier are vulnerable, and Bun 1.4.4 includes the fix. 

How the Node2Shell bug (CVE-2026-111497) works 

Brotli is a compression format. Node.js supports it through the native decoder in its zlib module. The CVE record describes a buffer overflow in c/dec/decode.c and lists two weakness types: out-of-bounds write (CWE-787) and unchecked return value (CWE-252).

The second weakness explains the mechanism. The crafted stream declares one type of data block, then asks the decoder to switch block types. A correct decoder stops with an error. The unpatched decoder ignores the error and keeps going, writing past the end of its buffer. Semgrep describes the underlying defect as the decoder confusing incomplete input with invalid input and continuing to process a malformed stream. 

The fix is small. Node.js cherry-picked an upstream Brotli commit (0ed4268a) that makes the decoder fail immediately on a block switch when the stream declares only one block type. Node.js also added a new error constant, BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH.

What is reachable

Node.js does not decode Brotli on its own. An app is exposed when its code, or a library it uses, decompresses Brotli data an attacker controls. Semgrep confirmed several entry points: 

Path

Reaches the decoder?

Details

Express 5 with express.json()

Yes, by default

Express 5.3.0 depends on body-parser ^2.3.0. body-parser 2.x decodes br bodies, and its inflate option defaults to true. A bare Node.js HTTP server doesn’t decode incoming Brotli bodies on its own.

Express 4 with express.json()

Not through body-parser

body-parser 1.20.x handles only deflate and gzip and answers 415 to other encodings.

Server-side fetch()

Yes, for attacker-influenced responses

Node.js fetch decompresses a response with the Brotli decoder whenever the Content-Encoding header contains br. Sending Accept-Encoding: identity does not prevent it. Features that call user-supplied URLs are typically targets, like webhooks.

Direct node:zlib use

Yes

createBrotliDecompress() is exposed when it receives attacker-controlled data.

Koa (via co-body)

Yes

Brotli request bodies pass through co-body to inflation. Semgrep also lists @koa/bodyparser, koa-body, Egg and Strapi.

Fastify with @fastify/compress

Yes

Registering the plugin adds request decompression before Fastify’s content-type parsers run.

The inbound path should be prioritized. When mounted globally, body-parser can reach many public body-bearing routes, subject to the content-encoding and parser conditions. However, the outbound path also matters. If an organization’s service fetches from a server an attacker controls, the response can attack the service.

This doesn’t leave Express 4 with a clean bill of health. That reading covers body-parser only. Other middleware, frameworks, reverse proxies, and an organization’s own code may still decode Brotli. 

Node2Shell exploitation: What’s been demonstrated vs. claimed

Imperva has demonstrated code execution against the official Node.js 24.22.0 image on Linux arm64, and noted that execution required several attempts. On freshly started containers without a debugger or modified binaries, the test ended with a marker file, and the patched 24.22.1 rejected the same inputs with a format error. Imperva has not released its exploit code. 

As far as what the public PoCs do, on October 22 at 20:28 UTC, a GitHub search returned 11 repositories. One lab reported crashes on Node.js 20.19.5, 22.23.3, 24.22.0, and 26.12.0, and says the fixed 22.23.4, 24.22.1, and 26.12.1 reject the same input. Another team reported local command execution in three of three runs, but it needed a build that loads an unfixed system Brotli library plus a predictable memory layout. That team says blind remote execution with address randomization on did not work. 

However, some of the evidence is thin. Research has argued that no Brotli stream can reach the bad write and the real impact is denial of service. An independent test of the fix commit’s input on Node.js 24.22.0 produced an error on both the pre-fix and patched builds, so that test alone can’t show the write happens. Konfirmity notes that the fix commit itself describes the bug as low severity and not easy to exploit. 

Reliable remote code execution (RCE) has been reproduced in only one setup to date. Crashes, by contrast, have been easy for researchers to reproduce. Organizations should treat a crash as the likely outcome everywhere, and the shell as a credible risk wherever their service decodes instances of Brotli that may be attacker-controlled.  

Node2Shell impact

Nothing publicly disclosed at the time of publication shows a worm, a mass-exploitation campaign, or a reliable cross-platform exploit. But researchers have proven the following:

  • Denial of service: Public PoC authors report the process crashes on unpatched Node.js, per the repositories described above. An attacker can take down any service that decodes Brotli from users.
  • Code execution under the Node.js process: Imperva showed this on one image and architecture, with repeated attempts. An attacker’s code would run with the permissions of the Node.js process and could steal data. 
  • Memory disclosure: Vercel says researchers showed memory disclosure and command execution in the Node.js process on unpatched 22.x, 24.x, and 26.x. Even when code execution fails, leaked memory can expose data such as credentials. 

How to detect Node2Shell

Sysdig Secure customers who use managed policies now have detections to identify and respond to Node2Shell. A Threat Intelligence entry shows where the exposure is, and runtime rules catch exploitation and the attacker activity that follows.

Threat intelligence

The Sysdig Threat Intelligence feed has published a Node2Shell entry. It lists the hosts and workloads that run a Node.js version below the fixed releases 26.12.1, 24.22.1, and 22.23.4, or an end-of-life line. Select the host or workload count to open a filtered search of the affected assets.

Runtime detection
Exploitation is rarely clean. Failed attempts crash the Node.js process, and Imperva’s own demonstration needed several tries. The new managed rule Node.js Process Crash Followed by In-Place Program Execution, in the Sysdig Runtime Behavioral Analytics policy, correlates a Node.js crash with suspicious program execution that follows it in the same workload. This is the pattern of a Node2Shell exploitation chain.

If the exploit succeeds, the attacker can run commands as the Node.js service user. Common next steps include an interactive shell, a malware download, cryptomining, or theft of secrets and cloud tokens from the container. The managed policies that Sysdig Secure enables by default already alert on this kind of activity. Customers have coverage even if the exploit itself goes unseen.

How to mitigate Node2Shell

Patch

  • Update Node.js to 22.23.4, 24.22.1, or 26.12.1. Imperva says only a Node.js update fixes the decoder. 
  • Upgrade Bun to 1.4.4 or newer wherever it runs.
  • Rebuild container images from a patched base, then verify with node --version in the running container. A floating tag like node:24 stays on the old version if you rebuild from a cached image, so run docker pull first. Move your Dockerfile pin to 24.22.1 or later.
  • Check package managers before assuming. Homebrew still shipped node 26.12.0, node@24 24.22.0, and node@22 22.23.3 about 10 hours after release.
  • Replace Node.js 20 and older with 22.x or 24.x. No fix will ship for them.

Reduce reachability while you patch

  • Disable request decompression where you can. In body-parser, express.json({ inflate: false }) rejects compressed bodies with a 415. Test your clients first. This also rejects gzip.
  • Reject Content-Encoding: br on request bodies at the proxy or load balancer where your clients don’t send it. Brandefense proposes this as its own suggestion, not vendor guidance. Test it before relying on it. It does not cover responses your services fetch. 
  • Audit fetch calls to servers you don’t control, and any direct use of createBrotliDecompress().
  • Layer a WAF if you have one. Imperva says it added WAF rules and advises limiting untrusted Brotli traffic on affected paths. Treat this just as a layer and not as a fix. 

Contain the blast radius

  • Run Node.js services as an unprivileged user and keep secrets out of the process environment wherever possible. Code execution lands with the permissions of the Node.js process. 
  • Monitor web-facing Node.js processes for shell spawns and unexpected outbound connections.

Across the estate

  • Inventory every Node.js runtime: containers, CI runners, serverless functions, build servers, and tools that ship their own Node.js.

Conclusion

Node2Shell is not a bug in every Node.js service, but a bug in services that decode attacker-influenced Brotli. Express 5 with default JSON parsing puts a large number of instances of them in that group. The demonstrated impact thus far is crashes at scale and code execution in a narrow configuration, so patch order should follow reachability.

The timeline, however, is the real warning. In the case of Node2Shell, a public repository tracking the CVE appeared five hours after the fix shipped, and a working PoC was public within a day. Since this flaw sits in a native library that Node.js and other software bundle, each must ship its own fix. Therefore, security teams should also expect more of them to be discovered — in the native libraries under the runtimes — on an increasingly short clock. 

For security teams, this week’s work is inventory, then patching in order of reachability, then least privilege for whatever remains unpatched. A runtime sensor will not see the overflow, but it will catch what a successful exploit does next. That’s what makes post-exploitation behavior the backstop worth paying attention to.

‍

About the author

featured resources

Test drive the right way to defend the cloud
with a security expert