Skip to main content

Node2Shell: Node.js Flaw Opens the Door to Remote Code Execution

Updated 16 min readMarkdown
Part of seriesNewsletters-eng
Node2Shell: Node.js Flaw Opens the Door to Remote Code Execution

Node2Shell (CVE-2026-111497) stems from the Brotli decoder bundled with Node.js. It lets a remote, unauthenticated attacker crash the process, leak memory or execute arbitrary code when an application decompresses malicious data. On October 27, 2026, CISA added the flaw to its KEV catalog based on evidence of active exploitation. Administrators should inventory their services, upgrade to a patched release and restart processes now.

Executive Summary

On October 21, 2026, the Node.js project released an urgent fix for Node2Shell (CVE-2026-111497) in its bundled Brotli decoder. The flaw lets a remote, unauthenticated attacker crash the process, leak memory or execute arbitrary code when the application decompresses a malicious data stream.

The business risk is significant for any Node.js service that calls external APIs, handles webhook responses through fetch(), or accepts Brotli-compressed uploads. Urgency rose sharply on October 27, 2026, when CISA added CVE-2026-111497 to the KEV catalog based on evidence of active exploitation.

The most important action: upgrade Node.js to a patched release (22.23.4, 24.22.1, 26.12.1), restart worker processes and rebuild container images so the old decoder is gone from memory.

Vulnerability Details

CVE-2026-111497 is an out-of-bounds write in the Brotli decoder bundled with Node.js, triggered when the decoder processes malformed Brotli data; according to Node.js, the impact ranges from a process crash and memory disclosure to remote code execution. The flaw maps to CWE-252 and CWE-787.

No authentication is required. The attacker only needs to get Brotli data to a place where the application decompresses it.

Imperva says "Node2Shell" is the name its Red Team gave to its analysis; Aikido describes it as the name circulating online and later used "HTTP2Shell" as the impact spread to many HTTP libraries.

Severity ratings by organization

Organizations rate CVE-2026-111497 on different scales. The published ratings are summarized below:

Rated by Score and severity Scale Note
Google (CNA that assigned the CVE) 9.2 (Critical) CVSS v4.0 Google assigned the CVE (per THN).
Node.js High Node.js severity scale Per the Node.js advisory.
Red Hat 8.1 (Important) Not stated by the source Per THN.
Microsoft 8.1 (High) Not stated by the source Rating for .NET (per THN).

Affected Node.js versions

The October 21, 2026 Node.js release fixed 10 CVEs (4 high, 3 medium, 3 low). CVE-2026-111497 is one of the four high-severity flaws.

Release line Support status Patched version Recommended action
Node.js 26.x Current 26.12.1 Upgrade to the patched version now.
Node.js 24.x Long-Term Support (LTS) 24.22.1 Upgrade to the patched version now.
Node.js 22.x Long-Term Support (LTS) 22.23.4 Upgrade to the patched version now.
25.x, 23.x, 20.x and older End of Life (EOL) No fix Move urgently to a supported LTS line.

Node.js installed from distribution repositories (Debian, Ubuntu, Fedora, RHEL, Alpine) may use the system Brotli library. In that case the fix arrives through the distribution's brotli package, and administrators need to follow the distribution's advisory.

Containers pinned to an old tag (such as node:24.22.0 or node:22.23.3-alpine) stay vulnerable even after a rebuild; the tag must be moved to a fixed release. A running process keeps the old decoder in memory until it is restarted. The Node.js advisory offers no temporary workaround.

Impact and Attack Paths

Node.js is only exposed when it actually decompresses Brotli data controlled by an attacker. If compressed data merely passes through without being decoded, the flaw is not triggered.

There are three main paths into the decoder:

  1. Client side, consuming network responses: Node.js's built-in fetch() automatically decompresses responses sent with Content-Encoding: br. A malicious server or a compromised API can attack the client application through its response. Services that call webhooks or user-supplied URLs are typical targets.
  2. Server side, receiving request bodies: Express 5 and body-parser 2.x decompress bodies sent with Content-Encoding: br when the parser is configured (such as raw(), json()). A bare Node.js HTTP server does not decompress Brotli bodies on its own.
  3. Code that calls the decoder directly: Applications that pass untrusted data to brotliDecompress or createBrotliDecompress from node:zlib.

A malicious client can take over an unpatched server that accepts compressed data. Conversely, a malicious server can take over an unpatched client that automatically decompresses network data (for example curl --compressed).

Imperva diagram of the two exposure paths

Figure 1: The two Node2Shell exposure paths (a response fetched with fetch() and a request sent to Express 5 / body-parser 2) both reach the Brotli decoder.

Timeline and Exposure Diagram

The risk picture around Node2Shell changed quickly:

Date Event Reported by
Feb 27, 2026 The fix lands in the Brotli source code (commit 0ed4268a), before anyone knew it addressed a vulnerability. Aikido, THN (citing OpenAI)
Oct 21, 2026 Node.js and Google ship fixes; Vercel adds firewall rules. Node.js, Aikido, THN
Oct 22, 2026 Imperva achieves code execution in the lab on a Node.js 24.22.0 Linux arm64 build after multiple attempts; the exploit is not released. The first public PoC only works against a deliberately weakened test build. Imperva, Aikido
Oct 23, 2026 CISA rates exploitation "none" and automation "no"; Red Hat says there is no reliable public PoC. Debian 13 updates its brotli package; PYSEC records are created for Python. THN (citing CISA, Red Hat)
Oct 24, 2026 The Hacker News reports the wider impact beyond Node.js; Amazon Linux 2023 ships fixed brotli and Node.js 24 packages; the Ruby brotli gem releases version 0.9.1. THN
Oct 25, 2026 Microsoft ships out-of-band .NET updates; Cloudflare adds 2 managed WAF rules (log-only by default); JFrog finds the flaw reaching FFmpeg, ClickHouse and Apache Arrow. THN
Oct 27, 2026 CISA adds CVE-2026-111497 to the KEV catalog based on evidence of active exploitation; the remediation due date for US federal agencies is November 10, 2026. CISA KEV, Rescana (citing the CISA alert)

(Bun 1.4.4 is not placed in the timeline because the sources give no release date.)

The diagram below shows the exposure paths and how the decoder behaves before and after the patch:

Figure 2: Node2Shell exposure paths from network data to the Brotli decoder, and decoder behavior after the patch.

Impact Beyond the Node.js Ecosystem

Because the Brotli decoder written in C is a widely shared library, the flaw appears in many other products:

Product / component Affected versions Fixed versions Exposed when
Google Brotli (C library) 1.0.3 to 1.2.0 1.0.10, 1.1.1, 1.2.1 The application decodes untrusted Brotli data.
Bun 1.4.3 and earlier 1.4.4 fetch() reads a br response, or node:zlib is used.
Microsoft .NET 8.0, 9.0, 10.0; 11.0 previews before RC3 8.0.33, 9.0.22, 10.0.14, 11.0 RC3 Only if Brotli is enabled in ASP.NET Core request decompression or HttpClient, or Brotli APIs decode untrusted data.
Envoy 1.39.2, 1.38.5, 1.37.7, 1.36.11 1.40.0, 1.39.3, 1.38.6, 1.37.8, 1.36.12 Only if the Brotli decompressor is configured.
Istio 1.31.0–1.31.1, 1.30.0–1.30.5, 1.29.0–1.29.8 1.31.2, 1.30.6, 1.29.9 Only if Brotli decompression is enabled.
Python Brotli 1.2.0 and earlier 1.2.1 The package is installed and an HTTP client decodes br responses.
Python brotlicffi 1.2.0.x and earlier 1.2.1.0 The package is installed and an HTTP client decodes br responses.
cdxgen Standalone binaries/images 13.4.0, 12.8.8 and earlier 13.5.0, 12.8.9 The tool scans untrusted input.

A note on Python and Dependabot

In Python, once the Brotli or brotlicffi package is installed, HTTP clients such as requests, urllib3, httpx and aiohttp automatically decode br responses. An application can be exposed without ever importing the library itself.

The CVE record names Google's Brotli repository rather than the PyPI packages. GitHub's advisory does not yet list an affected package, so Dependabot may not raise an alert. The PYSEC-2026-4322 and PYSEC-2026-4323 records were added on October 23, so teams should check installed versions manually.

Microsoft .NET

On October 25, 2026, Microsoft released out-of-band updates for .NET. Microsoft's advisory states that .NET Framework is not affected.

Microsoft says the flaw can lead to information disclosure, denial of service or elevation of privilege; its advisory does not list remote code execution. Self-contained and NativeAOT .NET applications must be rebuilt and republished, because the decoder is linked into the executable.

JFrog findings

JFrog's research on October 25 shows the impact reaching several data-processing tools:

  • FFmpeg: Exposed through libjxl (JPEG XL), which uses Brotli to decompress metadata. JFrog hijacked the program's control flow with a crafted image but said turning that into code execution would take considerably more work; JFrog reported no FFmpeg-specific fix.
  • ClickHouse: Decodes Brotli in request bodies, .br files and Parquet data. JFrog crashed the server with a request of about 23 MB (denial of service). A backport moving Brotli to 1.2.1 was merged into the 26.9 branch on October 26.
  • Apache Arrow C++: Bundles Brotli 1.0.9 and is exposed when reading Parquet or Arrow IPC files; no fix as of October 26.
  • pyarrow: The Python package falls into an endless loop that keeps the CPU busy with a 534-byte input (denial of service).

Some exposure paths start from a data file rather than an HTTP request. Blocking Content-Encoding: br at the network edge does not protect those file-processing paths.

Linux distribution updates

Patch progress differs between operating systems:

  • Debian: Debian 13 fixed on October 23 (1.1.0-2+deb13u1); Debian 12 fixed in 1.0.9-2+deb12u1.
  • Amazon Linux 2023: Shipped updated brotli and nodejs 24 packages on October 24.
  • openSUSE: Tumbleweed has completed the update.
  • SUSE Linux Enterprise 15: The Node.js 22 update was still in testing as of October 26.
  • Ubuntu: Still listed brotli and nodejs as "needs evaluation" as of October 26.

Detection & Threat Hunting

Defending against Node2Shell combines static asset version review with monitoring of network and host behavior.

Asset inventory commands for the SOC

Administrators can use the following commands to identify at-risk software versions:

1. Check Node.js versions on hosts and in containers:

# Check the version on a server or workstation
node --version

# Check the Node.js version inside a Docker image
docker run --rm <image_name> node --version

# List the Docker images running on the host
docker ps --format '{{.Image}}'

2. Review request parsing and decompression in the source code:

# Check Express and body-parser in a Node.js project
npm ls express body-parser

# Find Brotli decompression calls in application code
grep -rnE 'createBrotliDecompress|brotliDecompress' --include=*.js --include=*.ts --exclude-dir=node_modules .

# Review dependencies if needed
grep -rnE 'createBrotliDecompress|brotliDecompress' node_modules/

3. Check Python libraries and OS packages:

# Check Brotli libraries in Python
pip show brotli brotlicffi

# Check the brotli package on Debian or Ubuntu
dpkg -l | grep -i brotli

# Check the brotli package on RHEL, Fedora or Amazon Linux
rpm -qa | grep -i brotli

Behavioral Hunting

Note that an unexpected process crash or a decoder error alone is not enough to conclude that an attack took place. SOC teams should focus on three indicators:

  1. Unusual HTTP headers: Requests carrying Content-Encoding: br sent to endpoints that normally never receive compressed data.
  2. Repeated crashes: node or bun processes crashing several times in a short period without an obvious logic error.
  3. Processes spawning shells or download tools: A node process spawning a shell (sh, bash, dash) or a download tool (curl, wget).

Sigma detection rule

The following Sigma rule helps detect Node.js or Bun spawning a shell or download tool on Linux:

title: Suspicious Process Spawning from Node or Bun Runtime
id: 09f415fc-0e07-4db3-b046-d16fc596ede2
status: experimental
description: Detects Node.js or Bun spawning a shell interpreter or network download utility, a suspicious sign of code execution after exploitation of CVE-2026-111497.
references:
  - https://nodejs.org/en/blog/vulnerability/october-2026-security-releases
  - https://www.imperva.com/blog/node2shell-from-brotli-data-to-remote-code-execution/
author: FPT IS CSC - Threat Intelligence
date: 2026-11-04
tags:
  - attack.execution
  - attack.t1059.004
logsource:
  category: process_creation
  product: linux
detection:
  selection_parent:
    ParentImage|endswith:
      - '/node'
      - '/bun'
  selection_child:
    Image|endswith:
      - '/sh'
      - '/bash'
      - '/dash'
      - '/curl'
      - '/wget'
  condition: selection_parent and selection_child
falsepositives:
  - package.json scripts run through npm run or npx in CI/CD
  - Build tools or maintenance jobs that legitimately use child_process
  - Internal OS administration modules used on purpose by the application
level: medium

Network monitoring in Splunk (SPL)

The following query helps hunt for requests carrying the Brotli content-encoding header in proxy or WAF logs:

(index=proxy OR index=waf) (http_method=POST OR http_method=PUT)
| search http_content_encoding="br" OR http_content_encoding="*, br*" OR http_content_encoding="br,*"
| stats count min(_time) as first_seen max(_time) as last_seen by src_ip, dest_host, uri_path, http_content_encoding, http_user_agent
| sort - count

Note: Field and index names are placeholders; adapt them to your log schema. The query has not been run on a live SIEM.

Behavior monitoring in Microsoft Defender (KQL)

The following query helps detect child processes spawned by Node or Bun:

DeviceProcessEvents
| where InitiatingProcessFileName in~ ("node", "bun")
| where FileName in~ ("sh", "bash", "dash", "curl", "wget")
| project Timestamp, DeviceName, InitiatingProcessFileName, InitiatingProcessCommandLine, FileName, ProcessCommandLine, AccountName
| sort by Timestamp desc

Note: The KQL syntax is a starting point and has not been tested in a live Defender environment.

Assessment

Our analysis of Node2Shell leads to several key observations:

First, a shared open-source library creates a long patch tail. Because the flaw sits in the Brotli C library, fixes cannot be synchronized. Each product, whether Node.js, Bun, .NET, Envoy or a Linux distribution, has to package or backport the fix on its own. This fragmentation can leave dependent systems exposed for weeks [Inference]; as of October 26, Ubuntu still listed "needs evaluation" and Apache Arrow had no fix.

Second, the security impact of the fix was recognized late. The actual fix entered the Brotli project on February 27, 2026 in commit 0ed4268a. According to OpenAI, nobody knew at the time that the change fixed a vulnerability. As a result, for nearly eight months no Brotli release carried the fix to users.

Third, the risk picture shifted very quickly. In just four days, the status of CVE-2026-111497 reversed: from CISA's exploitation rating of "none" on October 23 to CISA itself adding it to KEV on October 27. Security teams cannot use the initial lack of a public PoC as a reason to delay patching.

Fourth, web application firewalls have limits. The path through responses that the application fetches itself is outside the reach of an edge WAF. When the application initiates the outbound connection, the response goes straight into the decoder without passing any inbound filter. Upgrading the runtime itself is the only protection for that path.

Fifth, Node2Shell and PHP2Shell show risk moving down into the runtime layer. Both flaws, disclosed in October 2026, sit in the execution environment rather than in application code. In our assessment, scanning application code alone (SAST) will miss this class of risk unless runtime versions are inventoried on every host and image [Inference].

Sixth, AI is taking part in finding bugs. This flaw was reported to Node.js by the OpenAI Codex Security team, and Imperva notes that AI can speed up both bug discovery and exploit development. The safe window between disclosure and patching may therefore shrink [Inference].

On the Vietnamese context [Inference], Node.js is widely used for API gateways and microservices that process partner webhooks. Pinning old base image tags in Dockerfiles or delaying service restarts can leave systems exposed even after they have been "updated" [Inference].

Comprehensive Defense Recommendations

Organizations should take a layered approach to address the risk:

Immediate actions (0–24 hours)

  1. Upgrade Node.js on servers:
    • Update Node.js to a patched release: 26.12.1, 24.22.1 or 22.23.4.
    • Restart the service so the new decoder is loaded into memory.
  2. Update and rebuild container images:
    • Change the tag in the Dockerfile to a patched release (such as node:24.22.1-alpine).
    • Rebuild all images and redeploy containers in production.
  3. Update related components:
    • Upgrade Bun to 1.4.4 or later.
    • For .NET, apply 8.0.33, 9.0.22, 10.0.14 or 11.0 RC3; rebuild NativeAOT and self-contained applications.
    • Upgrade Envoy and Istio, or update the Python Brotli/brotlicffi packages to 1.2.1, following the table above.
    • Update the OS brotli package on Linux servers.

Stopgap measures

If an immediate upgrade is not possible, apply the following temporary measures (they do not replace the patch):

  1. Block compressed requests at the edge: Block HTTP requests carrying Content-Encoding: br at an Nginx reverse proxy:

    # Temporarily block requests with the Brotli content-encoding header
    # Test first, as this may affect legitimate clients
    if ($http_content_encoding ~* "br") {
        return 415;
    }
    
  2. Disable automatic decompression in clients: Limit automatic decompression of external responses where possible. In Python, uninstall Brotli/brotlicffi so clients fall back to gzip or deflate.

  3. Accept-Encoding and WAF caveats: Removing br from Accept-Encoding is not enough, because a server can still send Brotli. Blocking at the edge does not cover responses the application fetches itself.

  4. Enable your provider's WAF rules: Cloudflare added 2 managed WAF rules that only log by default; switch them to block after checking legitimate traffic.

Medium- and long-term strategy

  1. Comprehensive SBOM management: Use SBOM tooling that captures the runtime and embedded libraries inside container images.
  2. A patch SLA for the runtime layer: Define clear emergency timelines for memory-safety flaws in execution environments.
  3. An EOL exit plan: Plan upgrades for systems running Node.js 20.x, 23.x or 25.x to current LTS lines, because those older lines get no fix.

References

  1. Node.js Security Team (Oct 21, 2026), Wednesday, October 21, 2026 Security Releases. URL: https://nodejs.org/en/blog/vulnerability/october-2026-security-releases
  2. Imperva Red Team (Oct 22, 2026), Node2Shell: From Brotli Data to Remote Code Execution. URL: https://www.imperva.com/blog/node2shell-from-brotli-data-to-remote-code-execution/
  3. Aikido Security (Oct 22, 2026, updated Oct 27, 2026), Node2Shell: Node.js Brotli vulnerability allows remote code execution (CVE-2026-111497) and the fix. URL: https://www.aikido.dev/blog/node2shell-nodejs-brotli-rce-cve-2026-111497
  4. The Hacker News (Oct 24, 2026, updated Oct 26, 2026), Brotli Decoder Flaw Behind Node.js RCE Also Affects Bun, Python and Other Widely Used Software. URL: https://thehackernews.com/2026/10/brotli-decoder-flaw-behind-nodejs-rce.html
  5. CISA (Oct 27, 2026), Known Exploited Vulnerabilities Catalog. URL: https://www.cisa.gov/known-exploited-vulnerabilities-catalog
  6. Rescana (updated after Oct 27, 2026), Node2Shell: Node.js Brotli Flaw CVE-2026-111497 Added to CISA KEV, used to cross-check the CISA alert. URL: https://www.rescana.com/post/nodejs-cve-2026-111497-node2shell-brotli-rce-october-2026

No comments yet. Be the first to comment.

More from this blog