Imperva Red Team demonstrated remote code execution against the official vulnerable Node.js build, then confirmed that the fixed release rejects the same Brotli input.

Executive summary

Node2Shell is Imperva Red Team’s name for our analysis of CVE-2026-111497, a High severity flaw in Node.js’s bundled Brotli decoder. Node.js says the out-of-bounds write can permit remote code execution and has released fixes for the 22.x, 24.x, and 26.x lines.

Our standalone proof of concept ran code carried in a Brotli response or request body inside applications using the official Node.js 24.22.0 Linux arm64 image. It needed no debugger or instrumented binary. The same inputs were rejected by 24.22.1. We tested Express 5.0.0–5.3.0 and body-parser 2.0.0–2.3.0, including the latest releases available at testing; execution took multiple attempts in our setup.

Imperva has added WAF rules for CVE-2026-111497. Customers should update affected Node.js deployments to a fixed release.

Overview

A Node.js service can encounter Brotli on either side of an HTTP exchange. It may consume a compressed response from another server, or use middleware to decode an incoming request body. Both operations can send untrusted data into the native decoder bundled with Node.js. That shared path is where CVE-2026-111497 lives.

We built a standalone proof of concept to see whether the flaw could lead to code execution in a Node.js application. In fresh containers running the official vulnerable Node.js image, the application ran code supplied with the Brotli data. We used a memory sanitizer separately to investigate the underlying bug and compared the results with the fixed release.

The Node.js project disclosed the issue on October 21, 2026. Its advisory credits Matteo Collina with reporting it and Antoine du Hamel with the fix. Our work is an independent validation of the impact and the released patch.

Impact: From a decoder error to code execution

In the working proof of concept, the test application had no code to create our marker file. After it received the Brotli data, the file appeared. Code carried in that data had run inside the target process. We reproduced this with the official Node.js 24.22.0 image in fresh Linux arm64 containers. The same inputs on Node.js 24.22.1 were rejected and created no marker.

We also investigated the cause. A source comparison showed that the vulnerable decoder could continue past an invalid stream condition. In a separate sanitizer test, decoding that condition caused an out-of-bounds write. The sanitizer helped explain the flaw; it was not needed for the code-execution proof.

We tested both a compressed response consumed by Node.js’s built-in fetch() and incoming Brotli bodies handled by configured request parsers. The table shows the Brotli-capable package ranges represented by our pinned endpoint tests:

Application path Package range and tested configurations Node.js 24.22.0 Node.js 24.22.1
Consumed HTTP response Node.js built-in fetch() Supplied code ran; marker created Input rejected; no marker
Incoming request body Express 5.0.0–5.3.0; tested 5.0.0 with body-parser 2.0.1, and 5.3.0 with body-parser 2.3.0 Supplied code ran with raw() and json() in both tested setups Input rejected; no marker; server stayed running
Incoming request body body-parser 2.0.0–2.3.0; tested 2.0.0 standalone and 2.0.1/2.3.0 through Express Supplied code ran with raw() and json() in the tested setups Input rejected; no marker; server stayed running

Express 5 documents Brotli decoding in its request-body parsers, and the body-parser release history records support beginning with 2.0.0. Express 5.3.0 and body-parser 2.3.0 were the latest releases when we tested on October 22, 2026. We reproduced execution at the listed versions; we did not individually test every intermediate release. The vulnerable code is in Node.js: these middleware versions identify paths that can invoke it. A bare Node.js HTTP server does not decode incoming Brotli bodies simply by receiving them.

The proof did not succeed on every attempt. Our results establish code execution for the tested Linux arm64 build and application setups, and show how the fixed build handled the same inputs. We did not test every Node.js build or application.

Technical deep dive: When invalid input looks incomplete

A Brotli stream describes the block types available as decoding progresses. Our test input reached a block transition that the stream’s own structure made impossible. In the vulnerable decoder, that condition could look like a request for more input. Processing continued with an invalid internal state.

Our separate sanitizer run showed that continuing from that state could write beyond an intended buffer. The upstream Brotli fix makes the decoder return a format error for the invalid transition and pass it to the caller. In our application tests, patched Node.js rejected the same inputs before code could run.

node2shell vulnerable recorder

Two tested routes into the native decoder. The patched runtime stops at the invalid-format check.

The distinction matters for exposure. Express 5 and body-parser 2 can decompress incoming Brotli request bodies when their parsers are configured; they are routes into the vulnerable Node.js decoder, not the source of the flaw. On the response side, our test service consumed an external Brotli response with Node.js’s built-in fetch(). Both paths reach the same decoder.

What defenders should do

The priority is to replace affected Node.js runtimes. The project released fixes in 22.23.4, 24.22.1, and 26.12.1. Deploy these or newer fixed releases in each line, including in container images and other artifacts that bundle a Node binary. Move applications on unsupported Node.js lines to a supported release.

Then map where untrusted Brotli data reaches that runtime. Review compressed responses consumed by services and incoming request bodies inflated by configured middleware. Check the Node.js version inside each deployed image or host; a package inventory can miss an older runtime bundled in a container.

Where practical, temporarily limit untrusted Brotli traffic on affected paths while updates roll out. Test changes against the application’s normal traffic. Complete remediation requires updating Node.js.

Unexpected process exits during decompression and decoder errors may help prioritize investigation. Neither is a reliable stand-alone sign of exploitation; correlate them with the deployed runtime, application logs, and the source of the compressed data.

Imperva’s response and customer protection 

Imperva has added dedicated WAF rules in response to CVE-2026-111497 and validated them to detect and block the exploitation attempts we were able to reproduce. Customers should update affected Node.js deployments to a fixed release. The runtime update remediates the decoder flaw. 

Our tests covered both an incoming request parser and a consumed HTTP response. In both cases the affected code is the Node.js decoder, so the runtime update addresses the shared cause. 

Closing Thoughts 

Node2Shell and the recent PHP2Shell research highlight the risk hidden in the runtimes beneath everyday web applications. In PHP2Shell, researchers used AI to help uncover and exploit longstanding memory-safety flaws. Our Node2Shell tests demonstrated how untrusted compressed data could lead to code execution in an official Node.js build.  

AI can accelerate both vulnerability discovery and exploit development, helping researchers investigate flaws while lowering the time and effort attackers need to turn those flaws into working attacks. For defenders, that means less room to delay between disclosure and remediation. 

In our tests, the fixed Node.js release rejected the same inputs that achieved code execution on the vulnerable build. The immediate priority is to deploy that fix wherever applications decode untrusted Brotli data. The broader lesson is that patching speed must keep pace with the tools making exploitation faster. Web Application Firewalls can help bridge that gap through virtual patching, buying defenders critical time to deploy permanent fixes.

The post Node2Shell: From Brotli Data to Remote Code Execution appeared first on Blog.