Node2Shell: Crafted Brotli Data Runs Attacker Code on an Official Node.js Build

Translated by a model; the original is in Russian.

· Security
Imperva researchers showed that an application on an official Node.js build can be made to run attacker-supplied code by feeding it a crafted Brotli stream (CVE-2026-111497). Node.js shipped fixes on October 21.

cover.svg

Security researchers at Imperva have demonstrated an attack they call Node2Shell: malicious Brotli data can make an application on an official build of Node.js run code supplied by an attacker. The flaw carries the identifier CVE-2026-111497; Node.js disclosed it and released fixes on October 21, and applications that decode untrusted Brotli data are urged to update.

Their proof of concept ran code on the official Node.js 24.22.0 image for Linux arm64 — with no debugger and no custom build — simply by feeding crafted data to the bundled Brotli decoder. The attack did not fire every time: in their Linux arm64 setup, code execution took several tries. The result covers that single build and application setup; other architectures, and the 22.x and 26.x lines, were 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 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. As of October 22, no exploitation in the wild has been reported.

Who is affected

The flaw sits in the Brotli decoder that Node.js bundles, so it affects the 22.x, 24.x and 26.x lines. A service reaches the decoder from either side of an HTTP exchange: when it reads a Brotli-compressed response through the built-in fetch(), or when middleware decodes a Brotli-compressed request body. Express 5's body parsers — express.json(), express.urlencoded(), express.text() and express.raw() — now decode Brotli request bodies alongside gzip and deflate. A plain Node.js HTTP server does not decode a Brotli request body just by receiving one; that takes such 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.

How the bug works

The cause lies in 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. Node.js fixed the flaw by importing an upstream Brotli patch that makes the decoder stop with a format error at that point.

What to do

The only fix is to move to a patched release. The update should reach container images and other artifacts that bundle a Node binary — something a package inventory can easily miss. Lines 20.x and earlier are end-of-life and will not receive the fix. There is no workaround inside Node.js. Imperva suggests limiting untrusted Brotli traffic on affected paths where practical, and has added rules to its own web application firewall. Vercel said it added rules on October 21 that block the attack in inbound requests, but they do not cover Brotli responses an application fetches from other servers.


Source: The Hacker News

Comments

Sign in, to comment.

  • No comments yet.