On October 21, 2026, Node.js fixed CVE-2026-111497, now known as Node2Shell. The bug is in its bundled Brotli decoder, the component that unpacks compressed data.
A crafted compressed stream makes the decoder write data outside the memory set aside for it, known as an out-of-bounds write. That can overwrite data the application relies on, so an attacker can crash the application, leak memory or run attacker code. Public proof-of-concept code was published within 24 hours. AppTrana WAAP customers are protected against the inbound attack path. Patching is still required to close the paths a WAF cannot see.
Risk Analysis
High (Node.js rating)
None yet
Remote code execution possible
A crafted Brotli request body, or a Brotli response from a server the application calls.
Public PoCs since October 22. Not in CISA’s Known Exploited Vulnerabilities (KEV) catalog as of October 23, 2026.
Node.js 22.23.4, 24.22.1, 26.12.1.
Node2Shell: From Patch to Public PoC in 24 Hours
February 27, 2026
The Brotli fix lands upstream, with no security note.
October 21, 2026
Node.js releases 22.23.4, 24.22.1 and 26.12.1.
October 22, 2026
Public PoCs appear. They crash and leak memory on standard builds. Researchers report unreliable code execution on an unmodified Node.js 24.22.0 on Linux arm64.
What is Node2Shell?
Node2Shell is a memory-safety vulnerability in the Brotli decoder that Node.js bundles in its zlib module. An attacker crafts a Brotli stream that is deliberately malformed: it declares one type of data block, then asks the decoder to switch block types. The decoder should stop with an error. An unpatched decoder ignores the error and keeps going, so it writes past the end of its buffer. The fix (Brotli commit 0ed4268a) stops decoding with a new error, BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH.
An attacker needs an application to decompress Brotli data that the attacker controls. This can happen in three ways:
Request bodies
The attacker sends a Brotli-compressed request body, marked with the Content-Encoding: br header. Express 5 and body-parser 2.x decompress these by default.
Outbound responses
The application calls a server the attacker controls, and the server replies with a Brotli response. Built-in fetch(), axios, node-fetch and got decompress it automatically.
Application code
The application passes attacker-supplied files or fields to zlib.brotliDecompress().
| Branch | Fixed version |
|---|---|
| Node.js 26.x | 26.12.1 Patched |
| Node.js 24.x | 24.22.1 Patched |
| Node.js 22.x | 22.23.4 Patched |
| 25.x, 23.x, 20.x and older | No fix. Upgrade to a supported line |
Linux distribution builds that use the system Brotli library also need the distribution’s brotli package updated.
What Node2Shell Means for Your Web Infrastructure
| Risk | What it means |
|---|---|
| Server takeover | An attacker’s code runs with the permissions of the Node.js process and can steal data. |
| Stolen credentials | Even when code execution fails, leaked memory can expose database credentials, API keys and cloud tokens. |
| Service outage | Each failed attempt can crash the process and take an API offline. |
| Attack through outbound calls | Webhooks, link previews, crawlers and AI agent tools fetch URLs that other people choose. A malicious server can reply with a crafted Brotli response that no inbound control sees. |
How to Detect Node2Shell
Find every Node.js runtime, including containers and CI. Then look for these signs from October 21 onwards:
Requests
Any Content-Encoding: br request body, which browsers and API clients do not send. Watch most for bodies over 1 MB or sent chunked (the published PoC is about 23 MB), duplicate Content-Encoding headers, and repeated Brotli requests from one IP.
Logs
ERR__ERROR_FORMAT_BLOCK_SWITCH means a patched runtime rejected an attack attempt. On unpatched servers, look for Brotli decoding errors, SIGSEGV crashes, restarts and HTTP 502/503 after a Brotli request.
Host activity
Node.js starting sh, bash, curl or wget, and unexpected outbound connections.
A crash alone does not prove exploitation. Check patched servers too, since patching does not remove an earlier compromise.
Node2Shell: Mitigation and Remediation
Upgrade to Node.js 22.23.4, 24.22.1 or 26.12.1. Rebuild container images with docker build –pull, restart services, and rotate secrets if you find signs of compromise. Until you can patch, these settings reduce exposure:
// Confirm the fix (run in a shell): prints -17 when patched
node -p "require('zlib').constants.BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH"
// Express 5: stop decoding compressed request bodies
app.use(express.json({ inflate: false }));
// axios / got: turn off response decompression
axios.get(url, { decompress: false });
A WAF blocks the inbound path, but it cannot see Brotli responses your application fetches. Patching is the only complete fix.
AppTrana WAAP Coverage for Node2Shell
AppTrana WAAP customers are protected against inbound Node2Shell attacks, in block mode by default, with no action needed.
Emergency rule update (22, Oct, 2026, 2026)
AppTrana blocks Brotli-compressed request bodies (Content-Encoding: br, including variants such as gzip, br) and duplicate Content-Encoding headers before they reach the origin. The Indusface security research team released the rules to all AppTrana sites after validating them for false-positive risk.
Continuous monitoring
The 24×7 managed services team tracks Node2Shell rule hits, obfuscated br values and PoC-sized streams across all customers.
Recommended actions for AppTrana customers
Keep applications in Block mode, enable Origin Protection, and upgrade every Node.js runtime. AppTrana protects you while you patch; outbound fetch() responses still need the runtime fix.
Protect Node.js applications with AppTrana WAAP
Block inbound Node2Shell attack attempts while your team patches every runtime.