Node.js Patches Critical Brotli Decoder Flaw That Allows RCE

A single malformed Brotli payload can crash a Node.js process, leak memory, or run attacker code. Node.js shipped a fix on October 21 — here is what you need to know.

The official Node.js hexagonal logo
The Node.js hex logo. Image: Node.js / OpenJS Foundation.

Node.js shipped a coordinated security release on October 21, 2026, fixing ten vulnerabilities across its three active release lines. The most serious of them, CVE-2026-111497, is an out-of-bounds write in Node's built-in Brotli decompression code that the Node.js project itself rates High severity and says "can lead to a crash, disclosure of process memory, or remote code execution." If you run Node.js and haven't updated since October 21, you should patch now; the fixed versions are 22.23.4, 24.22.1, and 26.12.1.

The short version:

  • CVE-2026-111497 is an out-of-bounds write in Node.js's bundled Brotli decoder, triggered by a malformed compressed input.
  • Node.js itself rates it High severity; Singapore's Cyber Security Agency rates it CVSS v3.1 9.8, critical.
  • Fixed in Node.js 22.23.4, 24.22.1, and 26.12.1, released October 21, 2026, alongside nine other patched issues.
  • No source has reported active exploitation as of this writing, and the flaw is not currently listed in CISA's Known Exploited Vulnerabilities catalog.
  • Any app that decompresses Brotli data from an untrusted source — including via Node's built-in fetch() — is a candidate for exposure.

What happened

Node.js runs coordinated security releases on a schedule it discloses in advance, bundling fixes so maintainers can patch everything at once rather than racing individual disclosures. October 21's release covered ten issues rated High, Medium, or Low, across the actively maintained 22.x, 24.x, and 26.x lines. Node.js's own advisory states plainly: "The highest severity issue fixed in this release is HIGH," and that High-severity issue is CVE-2026-111497.

The Brotli flaw, explained

Brotli is a general-purpose compression format, originally developed at Google, that Node.js bundles so it can decompress Content-Encoding: br HTTP responses and request bodies without an external library. According to Node.js's advisory, the bug is in how the decoder handles an invalid block switch in the compressed stream: that condition "was reported as a temporary need for more input instead of a permanent format error," so instead of stopping, the decoder kept writing past an eight-byte internal buffer. Written out past its boundary, attacker-controlled bytes can corrupt adjacent memory — the textbook setup for a crash at best, and code execution at worst, depending on what sits next to that buffer in a given process.

That's a meaningfully different, and more dangerous, class of bug than a typical parsing error. A parser that rejects bad input safely just returns an error. A parser that keeps writing past its buffer on bad input hands an attacker a lever to manipulate program memory directly.

Why Node.js bundles a Brotli decoder at all

Brotli is a general-purpose, lossless compression algorithm Google originally built for web fonts and later opened up for general HTTP use. Compared to the older gzip format most servers have used for decades, Brotli typically compresses text-heavy content — HTML, CSS, JavaScript, JSON — noticeably smaller at a similar or better compression speed, which is why most modern browsers and a growing share of servers prefer it when both sides support it. Node.js added native, built-in Brotli support (the zlib.brotliCompress()/brotliDecompress() functions, and transparent support inside the HTTP and fetch stacks) specifically so developers would not need a separate native-code dependency just to speak the compression format most of the modern web already uses by default. That convenience is exactly why this bug matters more than a flaw in some rarely-used corner of the standard library: Brotli decompression now runs, often invisibly to the developer, anywhere a Node.js app talks to a modern HTTP client or server.

Why severity ratings differ

You'll see different numbers attached to this flaw depending on the source, and it's worth knowing why. Node.js's own advisory assigns a qualitative rating of High rather than a numeric CVSS score. Singapore's Cyber Security Agency, in its own alert on the release, scored it CVSS v3.1 9.8 out of 10 — critical, just short of the maximum. That gap reflects different scoring methodologies and risk appetites between a software maintainer and a national cybersecurity agency rather than a disagreement about the underlying facts: both descriptions agree on what the bug does and which versions it affects.

Is your app affected?

The practical exposure test is simple: does any code in your application, or in a dependency it uses, decompress Brotli-encoded data that comes from outside your own infrastructure? That includes:

  • Any server that accepts Content-Encoding: br request bodies from users or external systems.
  • Any client code using Node's built-in fetch(), which auto-decompresses Brotli responses by default.
  • Web frameworks and HTTP clients that enable Brotli decompression automatically, since that removes the step where a developer would have had to opt in.

If your Node.js process never decompresses Brotli data that an outside party controls, the practical risk is lower — but since the fix touches core runtime code rather than an optional package, the simplest and safest move for almost everyone is to update rather than to audit every code path for exposure first.

If you maintain a library rather than an end-user application, the exposure question gets harder to answer in the abstract, because your users' own usage patterns determine whether the vulnerable code path is reachable. The safest approach if you publish a package that touches HTTP responses, compressed payloads, or wraps Node's fetch or zlib APIs is to bump your engines field or peer dependency range to require a patched Node.js version, and to call that out explicitly in your own release notes, rather than assuming downstream consumers will separately notice the Node.js advisory and connect it to your package.

Why some researchers are calling it "node2shell"

Several independent security researchers and blogs have taken to calling this flaw "node2shell" in their own write-ups, a name that deliberately echoes "php2shell," the nickname that stuck to a wave of critical PHP remote-code-execution flaws patched earlier this year. Node.js's own advisory does not use this name anywhere — it's industry shorthand, not an official designation — but it signals how seriously parts of the security community are treating a bug that can turn a routine decompression step into code execution.

The other nine vulnerabilities in this release

CVE-2026-111497 was the headline fix, but the same release patched nine other issues, several of them involving TLS certificate validation and DNS name handling — the kind of bug that can let a certificate meant for one host authenticate a connection to a different one. Node.js's advisory lists three other High-severity fixes: a dns.resolve() truncation bug involving embedded NUL bytes, and two separate TLS hostname-matching bypasses caused by non-standard numeric formatting of IP addresses (fullwidth digits in one case, non-canonical leading-zero octal-style notation in the other) that could let a certificate issued for one IP authenticate an endpoint it wasn't issued for. The release also bundled dependency updates, including a certificate authority update tied to the separate eMudhra intermediate CA compromise disclosed earlier in October.

A few of the Medium- and Low-severity fixes are worth knowing about too. CVE-2026-106074 affects crypto.randomUUID() and crypto.randomInt(): an entropy cache for these functions could be saved into a process snapshot or a single-executable application build, so two separate processes started from the same snapshot could generate the same values — a problem if your code relies on those identifiers being unique across instances. CVE-2026-106071 is a Permission Model bug specific to Node.js 26.x: a wildcard filesystem-read rule such as --allow-fs-read=/etc/passwd.* could unintentionally also grant read access to the exact file /etc/passwd, broadening a permission a developer thought was scoped narrowly. CVE-2026-106073 is a separate, incomplete fix of an older Permission Model bypass involving fs.realpathSync. None is as severe as the Brotli flaw, but all land in the same October 21 release, so updating once resolves them together.

Release lineVulnerable beforeFixed in
Node.js 22.x22.23.422.23.4
Node.js 24.x24.22.124.22.1
Node.js 26.x26.12.126.12.1
Node.js 20.x and earlierEnd of life — not patchedNot applicable

How to update right now

For most setups, updating is a short, low-risk operation given the severity of the bug it closes:

  • Using a version manager such as nvm: install the new patch version for your line (nvm install 22.23.4, 24.22.1, or 26.12.1) and switch your project to it.
  • Using a package manager install (apt, dnf, Homebrew, etc.): run your package manager's update command, then confirm with node -v that you're on a patched version.
  • In containers: rebuild from an updated base image that pins one of the patched versions, rather than relying on a floating tag that may not have refreshed yet.
  • If you're still on Node.js 20.x or earlier: those lines are end-of-life and did not receive this patch at all. The only fix is to upgrade to a maintained line — staying on an unsupported version leaves this and future vulnerabilities permanently unpatched.
  • In CI and deployment pipelines: check any pinned Node.js version in your CI config, Dockerfile, or platform-as-a-service settings (Vercel, Netlify, Heroku-style buildpacks, etc.) separately from your local environment — it's common for a developer's laptop to get updated while the version actually running in production stays on an older pin for months.

Is this being actively exploited?

As of this writing, no source reviewed for this article reports confirmed exploitation of CVE-2026-111497 in the wild, and it does not currently appear on CISA's Known Exploited Vulnerabilities catalog. That's a meaningfully different risk profile than an actively exploited zero-day, but a patched, publicly disclosed, critical-rated memory-safety bug in a runtime this widely deployed is exactly the kind of flaw that attracts exploitation attempts once the technical details are public, which they now are. Treat the absence of a confirmed attack today as a head start, not as a reason to delay.

What next

Update to 22.23.4, 24.22.1, or 26.12.1 (or later) and move on — this is a core-runtime fix, not something you can patch around with a dependency bump. If you maintain a service that others depend on, check whether your own Docker images, CI pipelines, or documentation pin an older patch version, since those references are easy to miss when you update your local machine but not your build infrastructure. For broader context on how Node's release and support lifecycle works, see our explainer on Node.js's LTS release model, and if you're deciding which runtime to standardize on, our comparison of Node.js against Deno and Bun covers how each handles security releases.

Finally, it's worth setting up a durable habit rather than treating this as a one-time fire drill: subscribe to Node.js's own security release mailing list or RSS feed, and make sure whoever owns your deployment pipeline is on it too. Coordinated disclosure only works as a defense if the people running the affected software actually see the advisory quickly — a critical fix sitting unread in an inbox for three weeks provides no more protection than no fix at all.

Frequently asked questions

What is CVE-2026-111497?

It's a critical, High-severity flaw in Node.js's built-in Brotli decompression code. A malformed compressed input can make the decoder write past an internal buffer, which can crash the process, leak memory, or lead to remote code execution.

Is Node.js being actively exploited right now because of this?

No confirmed exploitation has been reported as of this writing, and the CVE does not currently appear on CISA's Known Exploited Vulnerabilities catalog. That can change now that the details are public, so patching promptly is still important.

How do I know if my app is affected?

If your Node.js server or client ever decompresses Brotli-encoded data that comes from outside sources — including automatically, via the built-in fetch() API — you're a candidate for exposure. Since the fix is in core Node.js rather than an optional package, updating is simpler than auditing every code path.

What is "node2shell"?

It's an unofficial nickname some security researchers have given CVE-2026-111497, echoing the earlier "php2shell" naming for a wave of critical PHP flaws. Node.js's own advisory doesn't use this name; it's community shorthand, not an official designation.

How do I update Node.js to the patched version?

Install 22.23.4, 24.22.1, or 26.12.1 depending on your release line, using your version manager (like nvm), OS package manager, or by rebuilding container images from an updated base. Confirm the update with node -v.

Sources

More on Node.js →Node.jsCVE-2026-111497BrotliRemote code executionSecurity patch
Felix Moreau
Written byFelix Moreau

Felix Moreau writes Pandromeda's software coverage and how-to guides. He covers Windows, macOS and Linux updates, the apps people rely on, emulators and developer tools, and turns official documentation into clear, numbered steps that work on the current version.

More from Software & Guides

See all