CVE-2026-47137: vm2 Sandbox Escape via Strict Equality require Bypass
A maximum-severity sandbox escape tracked as CVE-2026-47137 has been identified in vm2, the popular Node.js sandbox library. With a CVSS v3.1 score of 10.0 (Critical), this flaw allows attackers to circumvent the require: false security restriction and escape the vm2 sandbox to execute arbitrary code on the host Node.js process.
The root cause is a strict equality check bug introduced in the fix for a prior CVE (GHSA-8hg8-63c5-gwmx / CVE-2023-37903). The mitigation used options.require === false (strict equality) instead of a truthy/falsy check, meaning any other falsy value for require — such as 0, "", null, or undefined — passes the guard and enables the restricted code path.
This vulnerability is patched in vm2 3.11.4.
Vulnerability Overview
| Attribute | Value |
|---|---|
| CVE ID | CVE-2026-47137 |
| CVSS Score | 10.0 (Critical) |
| Affected Software | vm2 Node.js sandbox — all versions < 3.11.4 |
| CWE | CWE-284 / Improper Access Control via logic bypass |
| Attack Vector | Local (sandboxed code execution) |
| Authentication Required | None — sandboxed context only |
| Primary Impact | Full sandbox escape and host code execution |
| Source | NVD / NIST (published 2026-06-12) |
| Fix | Upgrade to vm2 3.11.4 |
Background: The Prior Fix and Its Flaw
The Original CVE-2023-37903 Fix
The prior fix for CVE-2023-37903 (GHSA-8hg8-63c5-gwmx) added a check in nodevm.js at line 263 to block a dangerous combination:
nesting: true + require: false
The intent was: if nesting is enabled AND require is explicitly disabled, the combination is blocked because it represented a known sandbox escape path.
The check was written as:
// nodevm.js line 263 — the flawed check
if (options.nesting === true && options.require === false) {
throw new Error("..."); // Block the dangerous combination
}Why === false Is Insufficient
The === false strict equality check only matches the literal boolean false. JavaScript has many falsy values that evaluate to false in conditionals but do not equal false under strict equality:
| Value | === false | Falsy (behaves as false) |
|---|---|---|
false | ✓ | ✓ |
0 | ✗ | ✓ |
"" | ✗ | ✓ |
null | ✗ | ✓ |
undefined | ✗ | ✓ |
This means an attacker can supply require: 0 or require: null to satisfy vm2's interpretation of "require is disabled" while still passing through the guard:
// Attacker bypasses the security check:
const {NodeVM} = require('vm2');
const vm = new NodeVM({
nesting: true,
require: 0 // Falsy but not === false → bypasses the guard
});
vm.run(`
// Now inside a vm2 with nesting: true and effectively no require restriction
// Can use nesting to reach host realm...
`);Technical Exploitation Path
The bypass works because:
options.require === falseevaluates tofalsewhenrequireis0,null,"", etc.- The block is not executed — the "dangerous combination" guard is skipped
- The
nesting: truepath continues, which was the vector for the original CVE-2023-37903 escape - The attacker re-uses the original nesting-based escape technique that the patch was intended to block
In effect, the fix for CVE-2023-37903 contained a logic error that makes it trivially bypassable with a one-character change to the payload.
Impact Assessment
| Impact Area | Description |
|---|---|
| Host RCE | Attacker escapes vm2 sandbox and runs arbitrary code on host |
| Prior Patch Nullified | The CVE-2023-37903 fix is effectively defeated |
| Low Complexity | Bypass requires only changing require: false to require: 0 in existing exploits |
| Multi-tenant Exposure | Any platform using vm2 for tenant isolation is fully exposed |
| Supply Chain Risk | Libraries bundling vm2 internally inherit the bypass |
Detection
Look for vm2 initialization with non-boolean falsy values for require:
# Audit your codebase for potentially bypassed vm2 options
grep -r "require:" . --include="*.js" --include="*.ts" | grep -E "require:\s*(0|null|undefined|\"\")"Also audit transitive dependencies:
npm ls vm2
# or
yarn why vm2Remediation
Upgrade vm2 to 3.11.4
npm update vm2
# or
yarn upgrade vm2The fix in 3.11.4 changes the check to properly handle all falsy values:
// Fixed check (conceptual):
if (options.nesting === true && !options.require) {
throw new Error("..."); // Catches all falsy require values
}Consider Structural Mitigations
If you cannot immediately upgrade, consider:
-
Validate
requireoption type before passing to vm2:const requireOpt = typeof options.require === 'boolean' ? options.require : false; const vm = new NodeVM({ require: requireOpt }); -
Disable
nestingentirely if not needed — the dangerous combination requiresnesting: true. -
Migrate to OS-level isolation for untrusted code execution (Worker Threads, containers, Deno).
Related CVEs in This Batch
This is one of four vm2 sandbox escapes all fixed in version 3.11.4:
| CVE | Vulnerability |
|---|---|
| CVE-2026-47131 | Buffer prototype hijack via __lookupGetter__ + TypeError |
| CVE-2026-47137 (this advisory) | Strict equality bypass enables require: false circumvention |
| CVE-2026-47140 | Incomplete denylist — process and inspector/promises not blocked |
| CVE-2026-47208 | General sandbox breakout enabling arbitrary host command execution |
Key Takeaways
- CVE-2026-47137 is a CVSS 10.0 logic bypass — changing
require: falsetorequire: 0defeats vm2's own CVE-2023-37903 patch - Strict equality (
===) checks againstfalseare dangerous when you intend "falsy" — always use!valueor explicitly check the type - All vm2 versions prior to 3.11.4 are vulnerable, regardless of prior CVE remediation
- The low exploit complexity (one character change) means weaponized PoCs for the original CVE likely already bypass this
- Upgrade to vm2 3.11.4 or migrate to stronger sandboxing primitives