Node2Shell (CVE-2026-111497): What It Is and How to Fix It

Node2Shell (CVE-2026-111497) is a critical out-of-bounds write in the Brotli decoder bundled with Node.js. Learn how it works, who is exposed through Express 5 and fetch(), how to detect vulnerable assets, and how to patch.

0 comments
Node2Shell CVE-2026-111497 Node.js Brotli remote code execution vulnerability featured graphic

Key takeaways

  • Node2Shell (CVE-2026-111497) is a CVSS 9.2 heap overflow in the Brotli decoder bundled with Node.js.
  • Express 5 request bodies and fetch() responses reach the bug without any direct Brotli code.
  • Upgrade to Node.js 22.23.4, 24.22.1 or 26.12.1; end-of-life lines get no fix.
  • Restart processes and rebuild images, because running services keep the vulnerable decoder.
  • Set body-parser inflate to false or block br bodies at the proxy as interim controls.
  • Extend the review to Python Brotli packages, PAN-OS firewalls and vendored copies.
On this page
  1. What is Node2Shell?
  2. How does the Node2Shell vulnerability work?
  3. Why the disclosure timeline matters
  4. Which Node.js versions are affected by CVE-2026-111497?
  5. Who is exposed to the Node.js Brotli vulnerability?
  6. Path 1: Inbound request bodies through the Express 5 body-parser
  7. Path 2: Outbound HTTP responses through fetch()
  8. Path 3: Direct decoder calls
  9. Exposure beyond Node.js
  10. Is Node2Shell being exploited in the wild?
  11. How do you detect Node2Shell exposure in your environment?
  12. Step 1: Check the runtime version
  13. Step 2: Find the exposed code paths
  14. Step 3: Monitor traffic and process behaviour
  15. How do you fix Node2Shell?
  16. Remediation steps
  17. Interim mitigations while you patch
  18. What does Node2Shell mean for compliance and security governance?
  19. Conclusion: patch Node2Shell now and close the inventory gap

Node2Shell (CVE-2026-111497) is a critical out-of-bounds write in the Brotli decoder bundled with Node.js. Crafted Brotli data, sent as an Express 5 request body or returned to fetch(), can corrupt memory and enable remote code execution without authentication. Upgrade to Node.js 22.23.4, 24.22.1 or 26.12.1, then restart services.

Infographic listing six key takeaways on detecting and patching the Node2Shell vulnerability

What is Node2Shell?

Node2Shell is the nickname for CVE-2026-111497, a heap out-of-bounds write (CWE-787) in Google's Brotli C decoder that Node.js bundles inside its node:zlib module. Any application that decompresses Brotli data it does not control can have its process memory corrupted, which can end in a crash, memory disclosure or remote code execution (RCE).

The flaw was found by Khai Tran and Sylvie Mayer of OpenAI Codex Security and reported to the Node.js project. Node.js shipped fixed builds on October 21, 2026, and the CVE record was published on October 22. Google, acting as the CNA, scored it 9.2 Critical under CVSS 4.0, while the Node.js project rates it High.

The vulnerability is also known as "Broccoli2Shell" and "Brotli2Shell". Those alternative names exist for a good reason: the defect lives in the upstream Brotli library, not in Node.js itself, so its reach extends to Python packages, network appliances, media pipelines and any other software that ships the C decoder. This article focuses on Node.js, where the Node2Shell name originated, and then covers the wider blast radius that security teams must also inventory.

Three facts frame the risk for most organisations:

  • No authentication is required. An attacker only needs a path that delivers Brotli bytes to the decoder.

  • No direct API use is required. Applications that never call a Brotli function can still be exposed through the HTTP stack.

  • Exposure is widespread. Akamai reports that its telemetry shows 61% of networks running affected Node.js versions.

How does the Node2Shell vulnerability work?

Node2Shell is triggered by a Brotli stream that requests a block-type switch its own header has made impossible. The vulnerable decoder misreads that malformed state as "needs more input" rather than as a fatal format error, and keeps appending attacker bytes to an eight-byte internal buffer until it writes past the end.

Brotli splits compressed data into blocks and lets a stream signal when to switch between block types. Before the fix, the function DecodeBlockTypeAndLength() in c/dec/decode.c returned a plain boolean. Callers therefore could not distinguish a corrupt stream from a stream that was merely incomplete, and on the decoder's fast path the return value was ignored entirely. This combination is why the weakness is also catalogued as CWE-252 (unchecked return value).

The overflow corrupts adjacent decoder state on the heap. Public research has shown that this primitive can be shaped into code execution. Imperva's Red Team reported running attacker-supplied code on the official, unmodified Node.js 24.22.0 Linux arm64 image, delivering the payload both as a fetched HTTP response and as an Express request body. The exploit required several attempts because of address space layout randomisation (ASLR), but probabilistic reliability is not a meaningful defence for an internet-facing service that automatically restarts after a crash.

The upstream fix, Google Brotli commit 0ed4268, introduces a dedicated error code, BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH (value −17), and propagates it to the caller. Malformed streams are now rejected outright instead of being treated as incomplete input.

Why the disclosure timeline matters

The fix was committed to the public google/brotli repository on February 27, 2026, with no release and no advisory. It remained publicly readable for roughly eight months before patched Brotli releases (1.0.10, 1.1.1 and 1.2.1) and coordinated vendor advisories appeared in October 2026. For defenders, this is a reminder that "silent" upstream security commits can be discovered by anyone who diffs a dependency, and that software composition analysis should track upstream commit activity for critical parsers, not only published CVEs.

Which Node.js versions are affected by CVE-2026-111497?

Every supported Node.js release line was affected by CVE-2026-111497 before the October 21, 2026 security release. Upgrade to Node.js 22.23.4, 24.22.1 or 26.12.1 or later; end-of-life lines receive no fix and must be migrated.

Product

Affected

Fixed in

Node.js 26.x

Below 26.12.1

26.12.1

Node.js 24.x

Below 24.22.1

24.22.1

Node.js 22.x

Below 22.23.4

22.23.4

Node.js 25.x, 23.x, 20.x and older

All versions

No fix (end of life)

Bun

Below 1.4.4

1.4.4

Google Brotli C library

1.0.3 to 1.2.0

1.0.10, 1.1.1, 1.2.1

Python Brotli

1.0.3 to 1.2.0

1.2.1

Python brotlicffi

1.0.3 to 1.2.0.x

1.2.1.0

The authoritative sources are the Node.js October 2026 security release and the NVD entry for CVE-2026-111497. The same Node.js release fixed ten CVEs in total, including several TLS hostname-verification issues, so the upgrade carries benefits beyond Node2Shell.

One operational detail is frequently missed: Node.js bundles its own copy of Brotli. Patching the operating system's libbrotli package does nothing for a Node.js process. Only the Node.js runtime version matters.

Who is exposed to the Node.js Brotli vulnerability?

You are exposed to the Node.js Brotli vulnerability if your code, or any dependency, decompresses Brotli data that an external party controls. In practice, this happens through three paths, and two of them require no Brotli-specific code at all.

Path 1: Inbound request bodies through the Express 5 body-parser

Express 5 and body-parser 2 decode Content-Encoding: br request bodies by default in their json, raw, text and urlencoded parsers, because the inflate option defaults to true. Any unauthenticated client can therefore send a crafted compressed body to any route that uses these parsers. This is the highest-priority exposure for public APIs. Note that Express and body-parser do not contain the bug; they are only a delivery path, so upgrading them alone does not remediate CVE-2026-111497.

A bare node:http server does not decode request bodies on its own, so services built directly on the core HTTP module are exposed only if the application explicitly decompresses the body.

Path 2: Outbound HTTP responses through fetch()

Node.js's built-in fetch() automatically decompresses Brotli-encoded responses. A malicious or compromised server can therefore attack your application when it makes an outbound request. Common examples include webhook processors, link-preview generators, crawlers, "import from URL" features, and integrations with third-party APIs. Removing br from the Accept-Encoding header offers limited protection, because a hostile server can send Brotli regardless, and a perimeter WAF never sees responses your application fetches.

Path 3: Direct decoder calls

Applications that pass untrusted data to zlib.brotliDecompress(), zlib.brotliDecompressSync() or zlib.createBrotliDecompress() are directly exposed. Look for this in file-upload processors, cache layers, message-queue consumers and archive handlers.

Exposure beyond Node.js

Because the flaw is in Google's reference C decoder, the wider ecosystem is affected. Teams should extend their inventory to:

  • Python services that have Brotli or brotlicffi installed. urllib3 (and therefore requests), aiohttp and httpx[brotli] use these packages automatically to decode responses.

  • Palo Alto Networks PAN-OS 11.2, 12.1 and 12.2 firewalls when TLS decryption and Brotli inspection are both enabled, which makes the firewall itself the target. See the Palo Alto advisory.

  • .NET, fixed in 8.0.33, 9.0.22 and 10.0.14.

  • FFmpeg builds with libjxl, which can reach the decoder through Brotli-compressed metadata in JPEG XL images.

  • Vendored copies in projects such as DuckDB, Apache Arrow and 7-Zip forks, which require their own rebuilds.

The independent tracker at broccoli2shell.com maintains a useful list of vendored copies and their patch status.

Is Node2Shell being exploited in the wild?

Yes. Threat intelligence firm ELLIO reported on October 26, 2026 that its sensors had recorded CVE-2026-111497 exploit traffic carrying a public exploit that it confirmed obtains a shell on vulnerable builds, according to Help Net Security.

The status changed quickly after disclosure, which is typical for a critical parser flaw with public research:

Date (2026)

Event

October 26

ELLIO reports in-the-wild exploit traffic; Palo Alto begins shipping PAN-OS hotfixes

October 23

CVE not yet listed in the CISA Known Exploited Vulnerabilities catalog

October 22

CVE published; Imperva research released; first public proof of concept appears on GitHub

October 21

Node.js releases 22.23.4, 24.22.1 and 26.12.1

February 27

Fix committed to google/brotli without a release or advisory

Reports on the early public proof of concept differ: some researchers noted it reached code execution only on deliberately weakened builds and otherwise caused a crash and limited memory read. Regardless, even the crash outcome is a reliable denial-of-service, and the threat picture has moved to active exploitation. Teams should treat Node2Shell as an emergency patch and check the CISA KEV catalog for a current listing.

How do you detect Node2Shell exposure in your environment?

Detect Node2Shell exposure by inventorying every Node.js runtime (hosts, containers, CI runners, serverless functions and developer machines), comparing each version against the fixed releases, and then prioritising instances that accept compressed request bodies or fetch untrusted URLs.

Step 1: Check the runtime version

Run the following on hosts or inside container images. The one-liner classifies the running binary against the fixed versions:

bash
node -e 'const [M,m,p]=process.versions.node.split(".").map(Number);const f={22:[23,4],24:[22,1],26:[12,1]}[M];const ok=!!f&&(m>f[0]||(m===f[0]&&p>=f[1]));console.log(process.version, ok?"PATCHED":"VULNERABLE_OR_EOL")'

# Record the bundled Brotli version for your asset inventory
node -p "process.versions.brotli"

# Inspect a container image without starting the application
docker run --rm --entrypoint node <image>:<tag> --version

Step 2: Find the exposed code paths

Search repositories for the three exposure paths. This prioritises which services to patch first:

bash
# Express 5 / body-parser 2 in dependency manifests
grep -RnE '"(express|body-parser)":\s*"[~^]?(5|2)\.' --include=package.json .

# Direct Brotli decoder usage
grep -RnE 'brotliDecompress|createBrotliDecompress' --include=*.js --include=*.ts --include=*.mjs .

# Outbound fetch() usage that may target untrusted hosts
grep -RnE '\bfetch\(' --include=*.js --include=*.ts --include=*.mjs . | grep -v node_modules

Step 3: Monitor traffic and process behaviour

At the edge, log and alert on inbound requests with Content-Encoding: br, which are uncommon for most APIs. On hosts, alert on unexpected Node.js process crashes and restarts, and on Node.js processes spawning shells (/bin/sh, bash) or making unusual outbound connections. EDR rules for "web runtime spawns interactive shell" remain one of the most effective post-exploitation signals for any RCE in this class.

How do you fix Node2Shell?

The only complete fix for Node2Shell is upgrading Node.js to 22.23.4, 24.22.1, 26.12.1 or later and then restarting every process and rebuilding every container image. The Node.js advisory publishes no workaround, so interim controls only reduce exposure while patching completes.

Remediation steps

  1. Upgrade the runtime. Use your version manager, package source or base image, for example nvm install 24.22.1, or pin FROM node:24.22.1-slim in Dockerfiles.

  2. Rebuild and redeploy containers. A running process keeps the vulnerable decoder in memory until it restarts, and an image keeps it until it is rebuilt on a patched base.

  3. Update lockfiles and pinned versions. Update .nvmrc, engines fields, CI matrices and base-image digests, or the next build will reintroduce the vulnerable runtime.

  4. Migrate end-of-life lines. Node.js 20.x, 23.x and 25.x receive no fix; plan the move to a supported line immediately.

  5. Patch the wider ecosystem. Upgrade Python Brotli to 1.2.1 and brotlicffi to 1.2.1.0, apply distribution libbrotli updates, and apply vendor hotfixes for appliances.

  6. Verify. Re-run the version check across the full inventory and confirm in your vulnerability scanner.

Interim mitigations while you patch

If an application does not need compressed request bodies, disable decompression in body-parser. Compressed requests are then rejected with HTTP 415 Unsupported Media Type:

javascript
import express from 'express';

const app = express();

// Reject Content-Encoding: br/gzip/deflate bodies (HTTP 415) until Node.js is patched
app.use(express.json({ inflate: false, limit: '100kb' }));
app.use(express.urlencoded({ extended: false, inflate: false, limit: '100kb' }));

At the reverse proxy, you can reject Brotli-encoded request bodies before they reach Node.js. In NGINX, place this in the relevant server or location block:

nginx
# Block Brotli-encoded request bodies (Node2Shell interim control)
if ($http_content_encoding ~* "(^|[\s,])br($|[\s,])") {
    return 415;
}

Finally, apply network segmentation. Restrict inbound access to Node.js services to the sources that need it, and restrict egress from those services to known destinations, so that a compromised process cannot easily reach internal systems or a command-and-control server. These measures do not fix the fetch() path, which only the runtime upgrade closes.

What does Node2Shell mean for compliance and security governance?

Node2Shell is a test of vulnerability-management maturity: a critical, remotely exploitable flaw in a transitive dependency that most asset inventories do not list explicitly. Organisations should treat the response as auditable evidence for their compliance programmes.

  • PCI DSS v4.0.1 Requirement 6.3.3 requires critical and high-severity security patches to be installed within one month of release. For in-scope payment systems, the October 21 release date starts that clock, and active exploitation justifies a much shorter internal target.

  • PCI DSS Requirement 6.3.2 requires an inventory of bespoke and custom software and third-party components. Node2Shell illustrates why that inventory must include runtimes and bundled native libraries, not only npm packages.

  • SOC 2 (CC7.1 and CC8.1) expects documented detection of new vulnerabilities and controlled change management. Keep records of the triage decision, the risk rating, the patch deployment and the verification scan.

  • Software bills of materials (SBOMs) should capture the Node.js runtime and its bundled components. Note that some Python scanners did not reliably flag the affected PyPI versions at disclosure, because the CVE record initially named the upstream repository rather than the packages.

From an architecture perspective, the incident reinforces a principle worth embedding in secure design standards: any decoder or parser that processes untrusted input is part of the attack surface, including decompression performed implicitly by frameworks and HTTP clients. Design reviews should ask which content encodings each service accepts, and whether that acceptance is a deliberate requirement.

Conclusion: patch Node2Shell now and close the inventory gap

Node2Shell (CVE-2026-111497) combines a critical CVSS 4.0 score of 9.2, unauthenticated reachability through default Express 5 behaviour and fetch(), public exploitation research and reported in-the-wild exploit traffic. That combination warrants emergency change procedures.

Your next step is concrete: run the version check across every environment today, upgrade to Node.js 22.23.4, 24.22.1 or 26.12.1, rebuild and redeploy all images, and set inflate: false on any service that does not need compressed bodies. Then extend the same review to Python services, appliances and vendored Brotli copies, and record the response as evidence for your PCI DSS and SOC 2 programmes. For deeper technical background, the Akamai Security Intelligence Group analysis and the Imperva research are the most detailed public references.

Questions and answers

Is Node2Shell the same as Broccoli2Shell?

Yes. Node2Shell, Broccoli2Shell and Brotli2Shell are all nicknames for CVE-2026-111497. The Node2Shell name came first because Node.js disclosed the flaw, but the defect sits in Google's Brotli C decoder. The alternative names emphasise that Python packages, firewalls, media tools and any software using the same decoder are also affected, not only Node.js.

What is the CVSS score of CVE-2026-111497?

CVE-2026-111497 carries a CVSS 4.0 base score of 9.2, rated Critical by Google as the CVE Numbering Authority. The Node.js project rates the issue as High severity in its own advisory. Most enterprise vulnerability programmes should use the Critical rating for prioritisation, particularly given public exploitation research and reported in-the-wild exploit traffic.

Does updating Express or body-parser fix Node2Shell?

No. Express 5 and body-parser 2 do not contain the bug; they only deliver Brotli-compressed request bodies to the vulnerable decoder inside Node.js. Upgrading those packages does not remediate CVE-2026-111497. You must upgrade the Node.js runtime itself, although setting the body-parser inflate option to false is a useful interim mitigation.

Does patching the system libbrotli package protect Node.js?

No. Node.js compiles its own copy of the Brotli library into the node binary, so the operating system's libbrotli package has no effect on Node.js processes. Distribution updates do protect other software that links libbrotli dynamically, such as some Python bindings and command-line tools, so apply both the Node.js upgrade and the system package update.

Is Node.js 20 affected by Node2Shell?

Yes. Node.js 20.x, together with 23.x and 25.x, is end of life and is affected, but it will not receive an official fix. Organisations still running these lines should migrate to Node.js 22.23.4, 24.22.1, 26.12.1 or later. Commercial extended-support vendors may offer patched builds as a short-term bridge while migration is completed.

Is Bun affected by CVE-2026-111497?

Yes. Bun bundles the same Brotli C decoder and was affected by CVE-2026-111497. The issue is fixed in Bun 1.4.4. Teams using Bun for APIs, scripts or build tooling should upgrade to 1.4.4 or later and rebuild any container images that embed an earlier Bun binary, following the same restart and redeploy discipline as for Node.js.

Can a WAF fully protect against Node2Shell?

No. A WAF or reverse proxy can block inbound requests with Content-Encoding: br, which closes the Express request-body path. It cannot see HTTP responses that your application fetches from external servers using fetch(), so the outbound path remains exposed. Treat WAF rules as a temporary risk reduction and complete the Node.js runtime upgrade as the actual fix.

How quickly should Node2Shell be patched under PCI DSS?

PCI DSS v4.0.1 Requirement 6.3.3 requires critical and high-severity security patches to be installed within one month of release. For Node2Shell, the clock starts with the Node.js release on October 21, 2026. Because exploit traffic has been reported in the wild, a target of days rather than weeks is a defensible risk-based decision for internet-facing payment systems.

Do I need to restart services after upgrading Node.js?

Yes. A running Node.js process keeps the vulnerable Brotli decoder loaded in memory until it restarts. After upgrading, restart every process manager instance, redeploy serverless functions and rebuild container images on a patched base image. Also update lockfiles, .nvmrc files and CI pipelines, otherwise the next build can silently reintroduce a vulnerable runtime version.

Are Python applications affected by Node2Shell?

Yes, if the Python packages Brotli (below 1.2.1) or brotlicffi (below 1.2.1.0) are installed. Popular HTTP clients such as requests, urllib3, aiohttp and httpx with the brotli extra use these packages automatically to decode responses. Upgrade both packages, update lockfiles, and verify manually, because some scanners did not reliably flag affected versions at disclosure.

What are the signs of a Node2Shell exploitation attempt?

Indicators include inbound requests with Content-Encoding: br to APIs that rarely receive compressed bodies, unexplained Node.js crashes or restart loops, and Node.js processes spawning shells or opening unusual outbound connections. Because the exploit can require several attempts, repeated crashes from the same source are a meaningful signal worth correlating in your SIEM.

Does disabling Brotli in Accept-Encoding stop the fetch() attack path?

Not reliably. Removing br from the Accept-Encoding request header asks the server not to use Brotli, but a malicious or compromised server can send a Brotli-encoded response anyway, and the client will still decode it. Only the patched Node.js runtime closes this path. Restricting egress to trusted destinations can reduce exposure in the meantime.

Who discovered the Node2Shell vulnerability?

Khai Tran and Sylvie Mayer of OpenAI Codex Security found the flaw and reported it to the Node.js project. Matteo Collina and Antoine du Hamel fixed it in Node.js, and Ron Masas of the Imperva Red Team published the exploitation research. Analysts at OpenSourceMalware and Aikido documented the impact on Python packages.

Are Palo Alto firewalls affected by CVE-2026-111497?

Yes, in specific configurations. PAN-OS 11.2, 12.1 and 12.2 on PA-Series and VM-Series firewalls are affected when TLS decryption and Brotli inspection are both enabled, because the firewall decodes Brotli traffic on its dataplane. Palo Alto is releasing hotfixes and documents disabling Brotli inspection as a temporary workaround. Panorama and the management interface are not affected.

How should vulnerable vendored Brotli copies be handled?

Treat vendored copies as separate assets. Projects such as DuckDB, Apache Arrow, 7-Zip forks and firmware toolkits bundle their own Brotli source, so a system update does not fix them. Identify them through SBOMs or source scanning, track each upstream project's fix, and rebuild with Brotli 1.0.10, 1.1.1, 1.2.1 or the cherry-picked upstream commit.

Sources

  1. Node.js October 2026 security release
  2. NVD entry for CVE-2026-111497
  3. Palo Alto advisory
  4. broccoli2shell.com
  5. Help Net Security
  6. Akamai Security Intelligence Group analysis
  7. Imperva research
0 comments

Discussion

Report an issue with this article

Spotted an error, outdated advice, a security concern or a broken link? Tell me and I'll review and fix it.

Only used to reply to you about this report.