Researchers at Imperva have demonstrated a critical code execution path — dubbed Node2Shell — against the official Node.js 24.22.0 build for Linux arm64. By feeding crafted Brotli-compressed data into the Brotli decoder bundled with Node.js (tracked as CVE-2026-111497), an attacker can achieve arbitrary code execution on the target process with no debugger, no custom build, and no local access required. If your organization runs Node.js services that decompress attacker-controlled Brotli data — HTTP content-encoding, reverse-proxied APIs, file upload pipelines, or message queues — treat this as a drop-everything remediation item.
What Happened
Imperva's research team built a working proof-of-concept that takes malformed Brotli data from the network to code execution on the stock node:24.22.0 Linux arm64 image. That last point matters more than the CVE number itself: most memory-corruption writeups die in the gap between "crash in a fuzzer" and "reliable RCE." This one did not. The exploit ran against a pristine, unmodified official binary — the exact artifact most organizations pull from Docker Hub or package repositories.
Node.js bundles Brotli for two primary surfaces:
Content-Encoding: brHTTP decompression — any Node.js server, framework middleware (Express, Fastify, Koa body parsers), or HTTP client that transparently decompresses Brotli responses.- The
zlibmodule API —brotliDecompressSync(),createBrotliDecompress(), and related calls used by applications to decompress user uploads, cached blobs, queue payloads, and archived assets.
Both surfaces are routinely exposed to attacker-controlled input in production. A web server accepting Brotli-encoded request bodies, an SSRF-reachable internal fetch, or a microservice decompressing queue messages all present a viable delivery channel.
Technical Analysis
Affected Products and Versions
- Node.js 24.x — confirmed exploitable on the official 24.22.0 build for Linux arm64
- Other architectures and earlier release lines (22.x LTS, 20.x LTS) should be treated as potentially affected until Node.js publishes its advisory scope — Brotli is bundled across all supported release lines, and the vulnerable decoder code is shared
- CVE: CVE-2026-111497 (disclosed by Node.js alongside the Imperva research)
How the Vulnerability Works
From the defender's perspective, the attack chain is:
- Delivery: Attacker submits crafted Brotli-compressed data to any reachable Node.js code path that invokes the bundled decoder — an HTTP endpoint accepting
Content-Encoding: br, an API ingesting compressed payloads, a file-processing worker, or a queue consumer. - Trigger: The Node.js process passes the data to the Brotli decoder. The malformed stream corrupts memory inside the decoder — memory-safety flaws in decompression libraries are a historically rich exploitation class because decoders perform complex, attacker-influenced pointer arithmetic at native speed.
- Execution: The corruption is steered into attacker-controlled execution within the Node.js process context. The payload inherits the full privileges, environment variables, cloud metadata access, and network reachability of the Node.js runtime — which in containerized deployments typically means IAM role credentials, database connection strings, and lateral-movement reach into the cluster.
No authentication, no local foothold, no debugger, no modified binary. The only prerequisite is reaching a decompression code path.
Exploitation Status
- Working PoC: Yes — Imperva demonstrated reliable code execution against the official
node:24.22.0Linux arm64 image - Active in-the-wild exploitation: Not confirmed at time of writing, but a public working PoC against an ecosystem as large as Node.js historically converts to exploitation quickly — expect weaponization within days, not months
- CISA KEV: Check CISA's KEV catalog for updates; given the PoC quality, KEV addition is a realistic near-term outcome
The defensive assumption: if your Node.js workload decompresses untrusted Brotli data, consider it exposed now.
Detection & Response
Memory-corruption exploits inside a long-lived runtime are hard to detect at the point of trigger — the crash-free exploitation happens in-process. Your highest-fidelity detections focus on post-exploitation behavior: Node.js processes spawning shells or system binaries, unexpected child processes, and egress connections from application containers. These are the behaviors the Node2Shell payload must exhibit to be useful to an attacker.
Sigma Rules
---
title: Node.js Process Spawning Shell or System Utility
description: Detects a Node.js process spawning a shell or common post-exploitation system binary. Strong indicator of in-process RCE such as the Node2Shell Brotli decoder exploit (CVE-2026-111497), where attacker code executes inside the node process and typically launches a shell or download cradle.
references:
- https://thehackernews.com/2026/10/researchers-demonstrate-node2shell-rce.html
- https://attack.mitre.org/techniques/T1059/
author: Security Arsenal
date: 2026/10/15
status: experimental
tags:
- attack.execution
- attack.t1059
logsource:
category: process_creation
product: linux
detection:
selection_parent:
ParentImage|endswith:
- '/node'
- '/nodejs'
selection_child:
Image|endswith:
- '/sh'
- '/bash'
- '/dash'
- '/zsh'
- '/curl'
- '/wget'
- '/nc'
- '/ncat'
- '/python'
- '/python3'
- '/perl'
- '/base64'
condition: selection_parent and selection_child
falsepositives:
- Build tooling and npm lifecycle scripts (postinstall hooks) legitimately spawning shells — scope by container/service context
- Node-based process managers and dev servers in development environments
level: high
---
title: Node.js Child Process Executing From World-Writable or Temp Path
description: Detects execution of binaries from /tmp, /dev/shm, or /var/tmp by a Node.js process tree — a common payload staging pattern after in-process code execution via memory corruption such as CVE-2026-111497 (Node2Shell).
references:
- https://thehackernews.com/2026/10/researchers-demonstrate-node2shell-rce.html
- https://attack.mitre.org/techniques/T1203/
author: Security Arsenal
date: 2026/10/15
status: experimental
tags:
- attack.exploitation_for_client_execution
- attack.t1203
logsource:
category: process_creation
product: linux
detection:
selection_path:
Image|startswith:
- '/tmp/'
- '/dev/shm/'
- '/var/tmp/'
selection_lineage:
ParentCommandLine|contains:
- 'node'
condition: selection_path and selection_lineage
falsepositives:
- Some build systems and self-updating tools stage helpers in temp paths — investigate parent chain and service context
level: high
KQL (Microsoft Sentinel / Defender)
If your Node.js workloads ship Syslog/auditd or Defender for Endpoint telemetry into Sentinel, this hunt surfaces Node.js processes spawning shells or staging payloads from temp paths — the post-exploitation fingerprint of Node2Shell-style in-process RCE.
// Hunt: Node.js spawning shells or temp-path payloads (post-RCE behavior)
// Relevant to CVE-2026-111497 / Node2Shell Brotli decoder exploitation
union isfuzzy=true
(DeviceProcessEvents
| where InitiatingProcessFileName =~ "node"
or InitiatingProcessCommandLine has "node"
| where FileName in~ ("sh","bash","dash","zsh","curl","wget","nc","ncat","python","python3","perl")
or FolderPath has_any ("/tmp/","/dev/shm/","/var/tmp/")
| project TimeGenerated, DeviceName, InitiatingProcessCommandLine, ProcessCommandLine, FileName, FolderPath, AccountName
),
(Syslog
| where Facility == "auth" or SyslogMessage has "node"
| where SyslogMessage has_any ("node","/tmp/","/dev/shm/")
and SyslogMessage has_any ("/bin/sh","/bin/bash","curl ","wget ","python")
| project TimeGenerated, Computer, ProcessName, SyslogMessage
)
| order by TimeGenerated desc
Velociraptor VQL
For live-response triage on Linux hosts and container nodes, this artifact identifies Node.js processes with suspicious child processes or listening/exec anomalies consistent with post-exploitation activity.
-- Hunt for Node.js processes spawning shells or staging payloads from temp paths
-- Triage artifact for suspected CVE-2026-111497 (Node2Shell) exploitation
SELECT Pid, Ppid, Name, Exe, CommandLine, Username, CreateTime
FROM pslist()
WHERE (
-- Node.js process with shell/system-utility children
Name =~ '(?i)^node'
AND Ppid IN (
SELECT Pid FROM pslist() WHERE Name =~ '(?i)^node'
)
) OR (
-- Any process executing from temp/world-writable paths under a node lineage
Exe =~ '^/(tmp|dev/shm|var/tmp)/'
AND CommandLine =~ '(?i)node'
) OR (
-- Shells with a node parent PID
Name =~ '(?i)^(sh|bash|dash|nc|ncat|curl|wget|python3?)$'
AND Ppid IN (
SELECT Pid FROM pslist() WHERE Name =~ '(?i)^node'
)
)
Remediation and Verification Script
Use this Bash script to inventory Node.js versions across your hosts and container images, flag vulnerable builds, and enforce a safe baseline. Run it on build agents, container hosts, and in CI to block deployments of affected images.
#!/usr/bin/env bash
# CVE-2026-111497 (Node2Shell) — Node.js Brotli decoder RCE inventory & verification
# Usage: sudo bash node2shell_check.sh
set -euo pipefail
VULNERABLE_VERSION="24.22.0"
echo "=== Node2Shell / CVE-2026-111497 exposure check ==="
# 1. Check system-installed Node.js
if command -v node >/dev/null 2>&1; then
SYSVER=$(node --version | tr -d 'v')
echo "[+] System Node.js version: v${SYSVER} ($(command -v node))"
if [ "${SYSVER}" = "${VULNERABLE_VERSION}" ]; then
echo "[!] VULNERABLE: official 24.22.0 build confirmed exploitable by Imperva PoC"
else
echo "[i] Not 24.22.0 — treat as potentially affected until Node.js advisory scopes all release lines"
fi
else
echo "[-] No system-wide node binary found"
fi
# 2. Find node binaries outside PATH (containers, bundled runtimes, sidecars)
echo "[+] Scanning for additional node binaries..."
find / -xdev -type f -name node -executable 2>/dev/null | while read -r bin; do
ver=$("$bin" --version 2>/dev/null || echo "unknown")
echo " ${bin} -> ${ver}"
done
# 3. Inventory running Node.js processes and their versions
echo "[+] Running node processes:"
for pid in $(pgrep -x node 2>/dev/null || true); do
exe=$(readlink -f /proc/"$pid"/exe 2>/dev/null || echo "unknown")
cmd=$(tr '\0' ' ' < /proc/"$pid"/cmdline 2>/dev/null || echo "unknown")
echo " PID ${pid}: ${exe} :: ${cmd}"
done
# 4. Audit container images for the vulnerable tag
echo "[+] Checking local container images for node:24.22.0 ..."
if command -v docker >/dev/null 2>&1; then
docker images --format '{{.Repository}}:{{.Tag}}' | grep -i node || echo " none found"
elif command -v crictl >/dev/null 2>&1; then
crictl images | grep -i node || echo " none found"
else
echo " no container runtime CLI available"
fi
# 5. Flag code paths that decompress Brotli from untrusted input
echo "[+] Scanning for Brotli decompression call sites in application source..."
for dir in /srv /opt /home /var/www; do
[ -d "$dir" ] && grep -rIl --include='*.js' --include='*.ts' --include='*.mjs' \
-e 'brotliDecompress' -e 'createBrotliDecompress' -e "Content-Encoding.*br" \
"$dir" 2>/dev/null || true
done
echo ""
echo "=== ACTION REQUIRED ==="
echo "1. Upgrade Node.js to the patched release per the Node.js security advisory."
echo "2. Until patched, do NOT decompress untrusted Brotli data (disable 'br' content-encoding"
echo " acceptance at your reverse proxy / load balancer as a temporary control)."
echo "3. Review the flagged source paths above for attacker-reachable decompression paths."
Remediation
- Patch immediately. Upgrade to the fixed Node.js release published in the official Node.js security advisory (monitor the Node.js blog and Imperva's disclosure for the exact patched version across 24.x, 22.x LTS, and 20.x LTS lines). Rebuild and redeploy all container images — do not rely on in-place package updates for long-running services.
- Temporary mitigation — strip Brotli at the edge. Until patches roll out, configure your reverse proxy / load balancer / WAF (NGINX, Envoy, HAProxy, Cloudflare) to remove
brfromAccept-Encodingand reject inbound request bodies withContent-Encoding: br. This severs the most common network-reachable delivery path without touching application code. - Audit decompression call sites. Inventory every use of
brotliDecompress*,createBrotliDecompress*, and transparent Brotli handling in HTTP clients. Any of these fed by request bodies, uploads, queue messages, or third-party API responses is an exposure. - Contain blast radius. Run Node.js workloads as non-root with read-only root filesystems, seccomp/AppArmor profiles restricting
execveof shells, and egress filtering. The exploit executes inside the node process — constrained process privileges directly degrade payload utility. - Hunt retroactively. Pull the last 30+ days of telemetry through the KQL query and Sigma logic above. With a public PoC in circulation, assume probing began at disclosure.
- Track CISA KEV. Monitor the CISA KEV catalog — a KEV listing would impose remediation deadlines for federal agencies and should accelerate your own patch SLA.
Related Resources
Security Arsenal Penetration Testing Services AlertMonitor Platform Book a SOC Assessment vulnerability-management Intel Hub
Is your security operations ready?
Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.