aighten
← Back to blog

Node2Shell CVE-2026-111497: Node.js Brotli RCE and Fixes

Node2ShellCVE-2026-111497Node.js Brotli vulnerabilityNode.js security release October 2026Brotli decoder out-of-bounds write+1 more
Node2Shell CVE-2026-111497: Node.js Brotli RCE and Fixes

Node2Shell is the nickname for CVE-2026-111497, an out-of-bounds write in the Brotli decoder that ships inside Node.js. A crafted Brotli stream can crash a Node.js process, leak its memory, or in some setups run attacker code. Node.js fixed it on October 21, 2026 in versions 22.23.4, 24.22.1 and 26.12.1, and credits the find to OpenAI's Codex Security agent. If your service decompresses Brotli data it does not control, update now.

The bug is in Google's Brotli library, not in Node.js's own code, so Bun, Envoy and Python's Brotli packages needed their own fixes too. A day after the release, Imperva ran code on an unmodified official Node.js image.

Key takeaways

  • Node.js 22.23.4, 24.22.1 and 26.12.1 fix the bug, per the Node.js October 2026 security release. End-of-life lines such as 25.x and 20.x get no fix.
  • Google, which issued the CVE, scores it 9.2 on CVSS v4.0 in the CVE record. Node.js rates it High.
  • Node.js credits the find to "OpenAI Codex Security (Khai Tran and Sylvie Mayer)". Envoy's advisory credits OpenAI Security Research.
  • Public proof-of-concept code exists. Imperva achieved code execution on Node.js 24.22.0 for Linux arm64. No in-the-wild attacks had been confirmed as of October 24.
  • The most exposed services are apps that call fetch() against untrusted servers, Express 5 with body-parser 2, and any code that runs node:zlib Brotli decompression on outside input.

What is Node2Shell (CVE-2026-111497)?

CVE-2026-111497 is a memory-safety bug in the Brotli decompressor (c/dec/decode.c) in Google Brotli versions 1.0.3 through 1.2.0. The CVE record describes it as a buffer overflow that lets "a remote unauthenticated attacker" corrupt decoder memory, disclose memory contents, cause a denial of service, "or potentially execute arbitrary code using a crafted Brotli-compressed stream."

Brotli is the compression format behind the br value in the HTTP Content-Encoding header. Browsers, CDNs and servers use it widely, and Node.js bundles its own copy of the decoder to support node:zlib.

The Node.js advisory explains the root cause in one sentence: "An invalid block switch was reported as a temporary need for more input instead of a permanent format error, so the streaming decoder kept appending input bytes to an eight-byte internal buffer." In plain terms, the decoder hit an impossible instruction in the compressed data, mistook it for "wait for more bytes," and kept writing past the end of a tiny buffer. The CVE record files it under CWE-787 (out-of-bounds write) and CWE-252 (unchecked return value).

Google published fixed Brotli releases 1.0.10, 1.1.1 and 1.2.1 on GitHub on October 21. The fix makes the decoder return a format error for that invalid transition.

Why it is called Node2Shell

The name comes from Imperva's research post, "Node2Shell: From Brotli Data to Remote Code Execution," published October 22. It follows the "-2Shell" naming used for other recent remote code execution bugs, including PHP2Shell. "Shell" means an attacker could get a command shell on the server, which so far has been shown in only one tested setup.

Diagram of three paths by which Brotli data reaches the vulnerable decoder in Node.js: fetch responses, Express 5 request bodies and direct node:zlib calls
Three common ways untrusted Brotli data reaches the bundled decoder in Node.js.AI-generated illustration / AightenAI-generated

Which versions are affected and fixed?

Every release on the supported 22.x, 24.x and 26.x lines before the fixed version is affected. So is every end-of-life line, because Node.js says EOL versions "are always affected" when a security release ships.

ProductVulnerableFixedSource
Node.js 26.x (Current)before 26.12.126.12.1Node.js advisory
Node.js 24.x (LTS)before 24.22.124.22.1Node.js advisory
Node.js 22.x (LTS)before 22.23.422.23.4Node.js advisory
Node.js 25.x, 20.x and olderallno fix (end-of-life)Node.js advisory
Google Brotli (C library)1.0.3 to 1.2.01.0.10, 1.1.1, 1.2.1CVE record
Bun1.4.3 and earlier1.4.4Bun v1.4.4 notes
Envoy (Brotli decompressor configured)v1.39.2, v1.38.5, v1.37.7, v1.36.11v1.40.0, v1.39.3, v1.38.6, v1.37.8, v1.36.12GHSA-3wvj-j6qm-62mr
Python Brotli / brotlicffi1.2.0 and earlier1.2.1 / 1.2.1.0PyPI: Brotli, PyPI: brotlicffi
Debian brotli packagebookworm 1.0.9-2, trixie 1.1.0-21.0.9-2+deb12u1, 1.1.0-2+deb13u1Debian tracker

The npm package named brotli is unrelated, so updating it does nothing; the vulnerable code lives in the Node.js runtime binary. Debian is a special case: its own nodejs package links the system Brotli library, so on Debian the fix arrives through the brotli package rather than a new Node.js version number.

The same Node.js release fixed nine other CVEs, including three more rated High: a DNS name truncation bug (CVE-2026-105482) and two TLS hostname-check bypasses (CVE-2026-105483 and CVE-2026-106069).

Who is actually exposed?

You are exposed if attacker-influenced Brotli bytes reach the decoder. Running a vulnerable Node.js version alone is not enough. According to the Node.js advisory, "An attacker who can supply Brotli data that an application decompresses with node:zlib" can corrupt process memory. In practice, that data arrives through three main routes:

  1. Outbound fetch(): Node.js's built-in fetch() decodes responses sent with Content-Encoding: br. A service that fetches user-supplied URLs (link previews, webhooks, scrapers, AI agents browsing the web) can receive a malicious response.
  2. Inbound request bodies: the body-parser README states that all its parsers "support automatic inflation of gzip, br (brotli), deflate", and the inflate option defaults to true. Express 5 uses body-parser 2, so a public Express 5 API decodes Brotli bodies by default. Sysdig also lists Koa (via co-body) and Fastify with @fastify/compress.
  3. Direct node:zlib calls: any code that runs brotliDecompress, brotliDecompressSync or createBrotliDecompress on uploaded files or queue messages.

Internal tools that only decompress their own data are lower priority. They still need the update, because Brotli input can come from places teams forget, such as a third-party API response.

How OpenAI's Codex Security found the bug

Node.js credits the report to "OpenAI Codex Security (Khai Tran and Sylvie Mayer)." Codex Security is OpenAI's application-security agent, which launched as a research preview to find, validate and fix vulnerabilities in codebases. Envoy's advisory for the same CVE credits "OpenAI Security Research."

The Node.js fix shipped on October 21, the same day as the fix for PHP2Shell, another set of old bugs that AI-assisted audits turned into working exploits. In both cases AI tools were reading old, widely shared C code, and every project that bundled that code had to ship its own fix. The LiteLLM supply-chain compromise, also on October 21, was a different kind of attack, but it points to the same risk: dependencies you did not know you had.

The timeline was short:

Date (2026)Event
October 16Google reserves CVE-2026-111497
October 21Google publishes Brotli 1.0.10, 1.1.1 and 1.2.1; Node.js ships 22.23.4, 24.22.1 and 26.12.1
October 22CVE record goes public; first public proof of concept; Imperva reports code execution; Bun 1.4.4, Python Brotli 1.2.1 and brotlicffi 1.2.1.0 ship
October 23Envoy publishes GHSA-3wvj-j6qm-62mr
October 24Sysdig reports no confirmed in-the-wild exploitation

How dangerous is it in practice?

Crashing a process is easy; running code is hard. Imperva's Ron Masas reports code execution on the official Node.js 24.22.0 Linux arm64 image, delivered both as a fetched HTTP response and as an Express request body. He also writes that it "took multiple attempts in our setup." Imperva has not published its exploit, and Node.js 24.22.1 rejected the same input.

The first public proof of concept, per HeroDevs' summary, reached code execution only on a deliberately weakened test build. On a standard build it produced a crash and a limited memory read. Nobody has publicly shown code execution on Bun, Envoy or the Python packages.

A crash alone still hurts. One malformed request that kills a Node.js worker is a cheap denial-of-service attack against any public Express 5 API. A memory leak can also expose tokens or keys held in the process.

How to patch Node2Shell and verify the fix

  1. Upgrade the runtime to 22.23.4, 24.22.1 or 26.12.1. These are patch releases with no API changes.
  2. Check what is actually running. Run node --version inside each running container, not just in your Dockerfile. Sysdig warns that a floating tag like node:24 can keep an old build if you rebuild from a cached image, so pull the base image again before rebuilding.
  3. Rebuild everything that embeds Node.js, including container images, serverless bundles, CI runners and single-executable apps, then restart the processes.
  4. Move off end-of-life lines. Node.js 20, 25 and older will not get an upstream fix, so move them to 22 or 24, or use a commercial extended-support build.
  5. Patch the neighbors: update Bun to 1.4.4, Envoy to the fixed release in its advisory, Python Brotli to 1.2.1, and distro brotli packages.
  6. While the rollout runs, Imperva suggests temporarily limiting untrusted Brotli traffic on exposed paths. With body-parser you can set the inflate option to false, which rejects all compressed request bodies (gzip included), so test it against real clients first.
  7. Watch for crashes. Imperva and Sysdig both treat unexpected Node.js exits and decoder errors as leads to investigate, not proof of attack. A crash followed by a new process running in the same container is the pattern to alert on.

FAQ

Is Node2Shell being exploited in the wild?

As of October 24, 2026, Sysdig reported no confirmed in-the-wild exploitation, and CISA had not added CVE-2026-111497 to its Known Exploited Vulnerabilities catalog as of October 23. Public proof-of-concept code exists, and Imperva showed code execution on one official Node.js build, so patch now rather than waiting for a KEV listing.

Does updating the npm "brotli" package fix CVE-2026-111497?

No. The vulnerable decoder is compiled into the Node.js runtime. Only Node.js 22.23.4, 24.22.1, 26.12.1 or later (or, on Debian, the patched system brotli package) remove the flaw.

I use Node.js 20. What should I do?

Node.js 20 is end-of-life and will not receive an upstream fix for CVE-2026-111497. Upgrade to Node.js 22.23.4 or 24.22.1. If you cannot upgrade soon, block or disable Brotli decoding of untrusted input and consider a commercial extended-support build.

Are browsers affected?

The CVE record and the advisories cited here cover the Brotli C library and the projects that bundle it, such as Node.js, Bun, Envoy and Python packages. None of them names a browser, so check your browser vendor's own release notes rather than assuming either way.

Who discovered Node2Shell?

Node.js credits OpenAI Codex Security, with researchers Khai Tran and Sylvie Mayer. Imperva later named the bug "Node2Shell" and demonstrated code execution.

Sources

Share this post