CVE-2026-100721

vm2 NodeVM Custom Resolver Path Boundary Bypass (CVE-2026-100721)

Execution Defense Evasion Last updated:

Detects exploitation and presence of CVE-2026-100721, a CVSS 10.0 authorization bypass (CWE-863) in the npm package vm2 at versions <= 3.12.1. When a NodeVM is configured with a custom module resolver, crafted require paths can bypass the configured external path boundaries, allowing sandboxed code to resolve and load modules outside the intended allowlist and escape the sandbox. This detection surfaces vulnerable vm2 installs, suspicious require() resolution patterns consistent with boundary bypass, and child-process/filesystem activity spawned from Node.js hosts running vm2.

Vulnerability Intelligence

Public PoC

What is CVE-2026-100721 vm2 NodeVM Custom Resolver Path Boundary Bypass (CVE-2026-100721)?

vm2 NodeVM Custom Resolver Path Boundary Bypass (CVE-2026-100721) (CVE-2026-100721) maps to the Execution and Defense Evasion tactics — the adversary is trying to run malicious code in MITRE ATT&CK.

This page provides production-ready detection logic for vm2 NodeVM Custom Resolver Path Boundary Bypass (CVE-2026-100721), covering the data sources and telemetry it touches: Microsoft Defender for Endpoint. The queries below are rated critical severity at medium confidence, and ship for 7 SIEM platforms — KQL, SPL, Elastic, QRadar, Sumo, YARA-L, LogScale.

MITRE ATT&CK

Tactic
Execution Defense Evasion
Microsoft Sentinel / Defender
kusto
// Detect vulnerable vm2 package presence and anomalous Node.js child process / file resolution post-exploit
let vulnPkg = DeviceFileEvents
| where FileName =~ "package.json"
| where FolderPath has "vm2"
| where FolderPath matches regex @"node_modules[\\/]+vm2[\\/]+package\.json$";
let suspiciousChild = DeviceProcessEvents
| where InitiatingProcessFileName in~ ("node.exe","node")
| where FileName in~ ("cmd.exe","powershell.exe","bash","sh","/bin/sh","child_process")
    or ProcessCommandLine has_any ("require('child_process')","require(\"child_process\")","process.binding","constructor.constructor","mainModule.require")
| project Timestamp, DeviceId, DeviceName, InitiatingProcessFileName, FileName, ProcessCommandLine, AccountName;
union 
(vulnPkg | project Timestamp, DeviceId, DeviceName, Evidence=strcat("vulnerable vm2 package.json at ", FolderPath)),
(suspiciousChild | project Timestamp, DeviceId, DeviceName, Evidence=strcat("suspicious node child: ", FileName, " :: ", ProcessCommandLine))
| sort by Timestamp desc

Finds vm2 package.json files under node_modules (for version triage) and correlates anomalous Node.js-spawned child processes or sandbox-escape command patterns (constructor.constructor, mainModule.require, child_process) indicative of a custom-resolver path boundary bypass.

critical severity medium confidence

Data Sources

Microsoft Defender for Endpoint

Required Tables

DeviceFileEvents DeviceProcessEvents

False Positives

  • Legitimate Node.js applications that spawn shells or child processes for build or automation tasks
  • Security scanners and SCA tools reading package.json files across node_modules
  • Developer workstations with many vm2 copies pulled in transitively that are never executed with untrusted input

Sigma rule & cross-platform mapping

The detection logic for vm2 NodeVM Custom Resolver Path Boundary Bypass (CVE-2026-100721) (CVE-2026-100721) above is provided in a vendor-neutral form so you can deploy it on any SIEM. The same logic is shipped here as native KQL (Microsoft Sentinel / Defender), SPL (Splunk), Elastic (Elastic Security (EQL)), QRadar (IBM QRadar (AQL)), Sumo (Sumo Logic CSE), YARA-L (Google Chronicle / SecOps), LogScale (CrowdStrike LogScale (CQL)) queries. In Sigma terms, this detection targets the following logsource:

logsource:
  category: process_creation
  product: windows

Browse the community-maintained Sigma rules for this technique:


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 1Inventory vulnerable vm2 version

    Expected signal: Process creation for node reading vm2/package.json; file read of node_modules/vm2/package.json

  2. Test 2Simulate NodeVM custom resolver boundary bypass (lab only)

    Expected signal: node process spawns a child shell (sh) running 'id'; command line contains constructor.constructor and mainModule.require

  3. Test 3Node spawns shell via child_process

    Expected signal: ProcessRollup/auditd event: parent node, child sh/bash running id


Response Playbook

Triage

  1. Confirm the vm2 version on the affected host by inspecting node_modules/vm2/package.json; any version <= 3.12.1 is vulnerable and must be upgraded to 3.12.2 or later.
  2. Determine whether the application uses NodeVM with a custom module resolver (customResolver / resolve option) and whether it executes untrusted or user-supplied code — if yes, treat as actively exploitable.
  3. Correlate the alerting node process with its command line and parent/child tree to confirm whether a shell or unexpected module load occurred around the alert time.
  4. Review application logs for require() calls resolving paths outside the configured external allowlist directories.

Containment

  1. Isolate the affected host or container from the network if a sandbox escape (shell spawn, unexpected child process) is confirmed.
  2. Disable or take offline the service that evaluates untrusted code via vm2 until the package is upgraded to >= 3.12.2.
  3. Rotate any credentials, tokens, or keys accessible to the Node.js process, since a vm2 escape grants full host-level code execution.

Evidence Collection

  1. Capture the full process tree (node parent and all children), their command lines, and loaded module paths for the incident window.
  2. Preserve node_modules/vm2/package.json, the application source invoking NodeVM, and any custom resolver configuration for version and exploitability confirmation.
  3. Collect application and container logs showing the require/resolve calls and any filesystem reads outside the intended boundary.

Escalation Criteria

  • ! Escalate to incident response if a shell, child_process, or outbound connection was spawned from the node process hosting vm2.
  • ! Escalate if the vulnerable service is internet-facing or accepts code/templates from untrusted users.
  • ! Escalate if evidence shows module resolution outside the configured external path boundary, indicating successful bypass exploitation.

Investigation Guide

Forensic Artifacts

  • > node_modules/vm2/package.json showing version <= 3.12.1
  • > Process creation records where node is the parent of a shell or child_process
  • > Application logs of require()/resolve() calls referencing paths outside the configured external boundary

Tuning Guidance

Baseline which Node.js applications legitimately spawn child processes (build tools, SSR frameworks, CI runners) and exclude those parent/child pairs. Focus severity on hosts that both carry vm2 <= 3.12.1 and run a service that evaluates untrusted code via NodeVM with a custom resolver. Reduce noise from SCA scanners by scoping file-event rules to execution-correlated events rather than package.json reads alone.


Hunting Queries

Inventory all hosts carrying a vm2 package to triage which installations are <= 3.12.1 and reachable with untrusted input.

Hunting — KQL
kql
DeviceFileEvents | where FolderPath matches regex @"node_modules[\\/]+vm2[\\/]+package\.json$" | project DeviceName, FolderPath, Timestamp
Hunting — SPL
spl
index=* sourcetype=*package* path="*node_modules/vm2/package.json*" | stats values(version) by host

Atomic Red Team Tests

Test 1 Inventory vulnerable vm2 version
linux

Check the installed vm2 version to confirm exposure to CVE-2026-100721 (vulnerable <= 3.12.1).

Command

bash
node -e "console.log(require('vm2/package.json').version)" || cat node_modules/vm2/package.json | grep '"version"'

Cleanup

bash
echo 'no cleanup required - read-only check'

Expected Telemetry

Process creation for node reading vm2/package.json; file read of node_modules/vm2/package.json

Expected Detection

File-event query surfaces the vm2 package.json path for version triage

Test 2 Simulate NodeVM custom resolver boundary bypass (lab only)
linux

Run a NodeVM sandbox with a custom resolver and attempt to resolve a module outside the configured external path boundary to reproduce the authorization bypass.

Command

bash
node -e "const {NodeVM}=require('vm2');const vm=new NodeVM({require:{external:true,root:'./allowed'},customRequire:(p)=>require(p)});vm.run(\"const cp=this.constructor.constructor('return process')().mainModule.require('child_process');cp.execSync('id');\",'exploit.js')"

Cleanup

bash
echo 'no artifacts to clean'

Expected Telemetry

node process spawns a child shell (sh) running 'id'; command line contains constructor.constructor and mainModule.require

Expected Detection

Process-creation rules match the node->sh child with sandbox-escape primitives

Test 3 Node spawns shell via child_process
linux

Baseline the detectable primitive: a node process spawning a shell that executes a command, mirroring post-escape behavior.

Command

bash
node -e "require('child_process').execSync('id', {stdio:'inherit'})"

Cleanup

bash
echo 'no cleanup required'

Expected Telemetry

ProcessRollup/auditd event: parent node, child sh/bash running id

Expected Detection

EQL/CQL/KQL rules match node-parented shell execution

Related Detections