Researchers Demonstrate Node2Shell RCE Exploit on Node.js Build Using Crafted Brotli Data

Malicious Brotli data can make an application on an official build of Node.js run attacker-supplied code, security researchers at Imperva have demonstrated.

Their "Node2Shell" proof of concept ran code on the official Node.js 24.22.0 image for Linux arm64, with no debugger or custom build, by feeding crafted data to the bundled Brotli decoder (CVE-2026-111497). Node.js disclosed the flaw and released fixes on October 21, and applications that decode untrusted Brotli data should update.

Imperva's test did not succeed on every attempt, and code execution took several tries in its Linux arm64 setup. The result covers that one build and application setup, with other architectures and the 22.x and 26.x lines not tested. On the fixed release, 24.22.1, the same data was rejected, and no code ran.

The demonstration goes beyond the first public proof of concept, which achieved code execution only on a deliberately weakened test build. On a standard build, that proof of concept's author reported a crash and a limited read of process memory, not code execution, and said a working attack on a normal build was not achieved.

No exploitation of the flaw in the wild has been reported as of October 22.

Which Applications Are Affected

The flaw is in the Brotli decoder that Node.js bundles, so it affects applications on the 22.x, 24.x, and 26.x lines, not only the one build Imperva tested. A service reaches that decoder from either side of an HTTP exchange: when it reads a Brotli-compressed response through Node.js's built-in fetch(), or when middleware decodes a Brotli-compressed request body.

Express 5's body parsers, such as express.json(), express.urlencoded(), express.text() and express.raw(), now decode Brotli request bodies when applied to a route, alongside gzip and deflate. A plain Node.js HTTP server does not decode a Brotli request body just by receiving one, so the decoding needs that middleware or an explicit call.

Imperva reproduced code execution through both the request-body and response paths, testing Express 5.0.0 to 5.3.0 and body-parser 2.0.0 to 2.3.0 at pinned versions, and did not test every release in between.

How the Bug Works

Imperva traced the cause to how the decoder handles an impossible point in a Brotli stream: the stream announces the block types it will use as decoding runs, and the test input reached a block change that the stream's own structure ruled out. The vulnerable decoder read that as a request for more input and kept going in an invalid state.

In a separate test with a memory sanitizer, continuing from that state wrote past an intended buffer, the out-of-bounds write behind the flaw.

Node.js fixed the flaw by importing an upstream Brotli patch that makes the decoder stop with a format error at that point instead of continuing.

What to Do

The fix is to move to a patched release. The update should reach container images and other artifacts that bundle a Node binary, which a package inventory can miss. End-of-life lines 20.x and earlier do not receive the fix and should be moved to a supported line.

The advisory lists no workaround inside Node.js, so an application that cannot update at once has no fallback in the runtime. Imperva suggested limiting untrusted Brotli traffic on affected paths where that is practical, and said only the update removes the flaw. The company also added rules to its own web application firewall and tested them against the attacks it reproduced.

Vercel, which runs Node.js for its customers, said it added rules on October 21 that block the attack in inbound requests. The rules do not cover Brotli responses an application fetches from other servers, and do not replace updating.

Dive deeper

Free tools to verify and analyze what this article covers:

source: TheHackerNews