CVE-2026-93605
vm2 NodeVM before 3.12.1 Remote Code Execution via child_process
vm2 NodeVM versions before 3.12.1 contain a sandbox escape vulnerability where the DANGEROUS_BUILTINS denylist omits child_process despite blocking other host-spawning modules. Attackers can require child_process and execute arbitrary commands on the host system when NodeVM is configured with builtin:['*'] or explicit child_process allowance.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- High
- Integrity
- High
- Availability
- High
Exploit likelihood
What each source reports
CVE List Score used
10.0
vm2 NodeVM before 3.12.1 Remote Code Execution via child_process
vm2 NodeVM versions before 3.12.1 contain a sandbox escape vulnerability where the DANGEROUS_BUILTINS denylist omits child_process despite blocking other host-spawning modules. Attackers can require child_process and execute arbitrary commands on the host system when NodeVM is configured with builtin:['*'] or explicit child_process allowance.
- Record
CVE-2026-93605- CVSS 4.0
- 10.0 Critical
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H - CVSS 3.1
- 10.0 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H - Weakness
- CWE-693
- Updated
- 2026-11-02
EUVDEUVD-2026-82900
10.0
vm2 NodeVM versions before 3.12.1 contain a sandbox escape vulnerability where the DANGEROUS_BUILTINS denylist omits child_process despite blocking other host-spawning modules. Attackers can require child_process and execute arbitrary commands on the host system when NodeVM is configured with builtin:['*'] or explicit child_process allowance.
- Record
EUVD-2026-82900- CVSS 4.0
- 10.0 Critical
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-9hxx-m5g2-2q3h
10.0
Duplicate Advisory: vm2 contains a sandbox escape vulnerability
Duplicate Advisory
This advisory has been withdrawn because it is a duplicate of GHSA-pq68-rvw4-xp4r. This link is maintained to preserve external references.
Original Description
vm2 NodeVM versions before 3.12.1 contain a sandbox escape vulnerability where the DANGEROUS_BUILTINS denylist omits child_process despite blocking other host-spawning modules. Attackers can require child_process and execute arbitrary commands on the host system when NodeVM is configured with builtin:['*'] or explicit child_process allowance.
- Record
GHSA-9hxx-m5g2-2q3h- CVSS 4.0
- 10.0 Critical
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - CVSS 3.1
- 10.0 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H - Weakness
- CWE-693
- Updated
- 2026-11-02
GitHub AdvisoriesGHSA-pq68-rvw4-xp4r
10.0
vm2 contains a sandbox escape vulnerability
vm2 NodeVM versions before 3.12.1 contain a sandbox escape vulnerability where the DANGEROUS_BUILTINS denylist omits child_process despite blocking other host-spawning modules. Attackers can require child_process and execute arbitrary commands on the host system when NodeVM is configured with builtin:['*'] or explicit child_process allowance.
This fork hardens NodeVM with a DANGEROUS_BUILTINS denylist that blocks host‑code‑reaching core modules even when the sandbox requests builtin:['*'] or names them explicitly — the list contains module, worker_threads, cluster, vm, repl, inspector, process, trace_events, wasi, diagnostics_channel, async_hooks, perf_hooks, v8, os, dns, and test. It omits child_process — the single most direct command‑execution primitive. As a result, a sandbox running under require:{builtin:['*']} (or the fork's own documented ['*','-http','-net',…] subtract pattern) can require('child_process').execSync(...) and execute arbitrary commands on the host. The omission is internally inconsistent: cluster is denied with the explicit rationale "cluster.fork() spawns a host child process running attacker‑controlled code," yet child_process — which spawns host processes more directly — is not.
Details
lib/builtin.js:
DANGEROUS_BUILTINS(lines 83‑179) — the Set of denied builtins.child_processdoes not appear anywhere in it.isDangerousBuiltin(key)(lines 185‑195) — stripsnode:prefixes and applies family‑prefix matching againstDANGEROUS_BUILTINS. Returnsfalseforchild_process.BUILTIN_MODULES(lines 209‑210) — the source list that the'*'wildcard expands to — isbuiltinModules.filter(s => !s.startsWith('internal/') && !s.startsWith('_') && !isDangerousBuiltin(s)). BecauseisDangerousBuiltin('child_process')isfalse,child_processremains in'*'.addDefaultBuiltin(the explicit‑name path) likewise rejects onlyisDangerousBuiltinnames, sobuiltin:['child_process']is admitted as well.
The module returned is the real host child_process (default require.context is "host"), so execSync/exec/spawn/fork run with full host authority. The denylist's own comment (lines 42‑44) states these primitives "must NEVER be reachable from the sandbox, even when the user requests '*' or explicitly names them" — the invariant child_process violates.
PoC
const { NodeVM } = require('vm2');
const r = new NodeVM({ require: { builtin: ['*'] } }).run(`
module.exports = require('child_process').execSync('id').toString();
`, 'plugin.js');
console.log(r); // -> "uid=1000(user) gid=1000(user) groups=..." host command execution
Verified results:
| config | require('child_process') |
|---|---|
| { builtin: ['*'] } | RCE — host id + host env read |
| { builtin: ['*', '-fs'] } (documented subtract pattern) | RCE — subtracting other modules does not remove it |
| { builtin: ['child_process'] } | RCE — explicit name admitted despite the "never, even if named" invariant |
| { builtin: ['fs'] } (control) | denied — Cannot find module 'child_process' |
Impact
Full host RCE — a complete NodeVM sandbox escape — for any deployment that runs untrusted code under require:{builtin:['*']} or the documented ['*', '-x', …] subtract pattern (both of which the fork explicitly supports and hardens), or that explicitly allows child_process believing the denylist would reject it as it does the other host‑spawning builtins. The attacker controls only their sandboxed script; the exploit is a single require('child_process').
builtin-child_process-denylist-gap-rce.js
'use strict';
// F-006: vm2 NodeVM DANGEROUS_BUILTINS denylist omits `child_process`.
// The fork's denylist (lib/builtin.js:83-179) blocks host-code-reaching builtins
// even under `builtin:['*']` or explicit naming —…
- Record
GHSA-pq68-rvw4-xp4r- CVSS 3.1
- 10.0 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H - Weakness
- CWE-693, CWE-913
- Updated
- 2026-11-02
NVD
10.0
vm2 NodeVM versions before 3.12.1 contain a sandbox escape vulnerability where the DANGEROUS_BUILTINS denylist omits child_process despite blocking other host-spawning modules. Attackers can require child_process and execute arbitrary commands on the host system when NodeVM is configured with builtin:['*'] or explicit child_process allowance.
- Record
CVE-2026-93605- CVSS 4.0
- 10.0 Critical
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - CVSS 3.1
- 10.0 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H - Weakness
- CWE-693
- Updated
- 2026-11-02
OSV
10.0
vm2 NodeVM before 3.12.1 Remote Code Execution via child_process
vm2 NodeVM versions before 3.12.1 contain a sandbox escape vulnerability where the DANGEROUS_BUILTINS denylist omits child_process despite blocking other host-spawning modules. Attackers can require child_process and execute arbitrary commands on the host system when NodeVM is configured with builtin:['*'] or explicit child_process allowance.
- Record
CVE-2026-93605- CVSS 4.0
- 10.0 Critical
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H - Weakness
- CWE-693
- Updated
- 2026-11-02
Show 5 moreShow less
OSVGHSA-9hxx-m5g2-2q3h
10.0
Duplicate Advisory: vm2 contains a sandbox escape vulnerability
Duplicate Advisory
This advisory has been withdrawn because it is a duplicate of GHSA-pq68-rvw4-xp4r. This link is maintained to preserve external references.
Original Description
vm2 NodeVM versions before 3.12.1 contain a sandbox escape vulnerability where the DANGEROUS_BUILTINS denylist omits child_process despite blocking other host-spawning modules. Attackers can require child_process and execute arbitrary commands on the host system when NodeVM is configured with builtin:['*'] or explicit child_process allowance.
- Record
GHSA-9hxx-m5g2-2q3h- CVSS 4.0
- 10.0 Critical
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - CVSS 3.1
- 10.0 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H - Weakness
- CWE-693
- Updated
- 2026-11-02
OSVGHSA-pq68-rvw4-xp4r
10.0
vm2 contains a sandbox escape vulnerability
vm2 NodeVM versions before 3.12.1 contain a sandbox escape vulnerability where the DANGEROUS_BUILTINS denylist omits child_process despite blocking other host-spawning modules. Attackers can require child_process and execute arbitrary commands on the host system when NodeVM is configured with builtin:['*'] or explicit child_process allowance.
This fork hardens NodeVM with a DANGEROUS_BUILTINS denylist that blocks host‑code‑reaching core modules even when the sandbox requests builtin:['*'] or names them explicitly — the list contains module, worker_threads, cluster, vm, repl, inspector, process, trace_events, wasi, diagnostics_channel, async_hooks, perf_hooks, v8, os, dns, and test. It omits child_process — the single most direct command‑execution primitive. As a result, a sandbox running under require:{builtin:['*']} (or the fork's own documented ['*','-http','-net',…] subtract pattern) can require('child_process').execSync(...) and execute arbitrary commands on the host. The omission is internally inconsistent: cluster is denied with the explicit rationale "cluster.fork() spawns a host child process running attacker‑controlled code," yet child_process — which spawns host processes more directly — is not.
Details
lib/builtin.js:
DANGEROUS_BUILTINS(lines 83‑179) — the Set of denied builtins.child_processdoes not appear anywhere in it.isDangerousBuiltin(key)(lines 185‑195) — stripsnode:prefixes and applies family‑prefix matching againstDANGEROUS_BUILTINS. Returnsfalseforchild_process.BUILTIN_MODULES(lines 209‑210) — the source list that the'*'wildcard expands to — isbuiltinModules.filter(s => !s.startsWith('internal/') && !s.startsWith('_') && !isDangerousBuiltin(s)). BecauseisDangerousBuiltin('child_process')isfalse,child_processremains in'*'.addDefaultBuiltin(the explicit‑name path) likewise rejects onlyisDangerousBuiltinnames, sobuiltin:['child_process']is admitted as well.
The module returned is the real host child_process (default require.context is "host"), so execSync/exec/spawn/fork run with full host authority. The denylist's own comment (lines 42‑44) states these primitives "must NEVER be reachable from the sandbox, even when the user requests '*' or explicitly names them" — the invariant child_process violates.
PoC
const { NodeVM } = require('vm2');
const r = new NodeVM({ require: { builtin: ['*'] } }).run(`
module.exports = require('child_process').execSync('id').toString();
`, 'plugin.js');
console.log(r); // -> "uid=1000(user) gid=1000(user) groups=..." host command execution
Verified results:
| config | require('child_process') |
|---|---|
| { builtin: ['*'] } | RCE — host id + host env read |
| { builtin: ['*', '-fs'] } (documented subtract pattern) | RCE — subtracting other modules does not remove it |
| { builtin: ['child_process'] } | RCE — explicit name admitted despite the "never, even if named" invariant |
| { builtin: ['fs'] } (control) | denied — Cannot find module 'child_process' |
Impact
Full host RCE — a complete NodeVM sandbox escape — for any deployment that runs untrusted code under require:{builtin:['*']} or the documented ['*', '-x', …] subtract pattern (both of which the fork explicitly supports and hardens), or that explicitly allows child_process believing the denylist would reject it as it does the other host‑spawning builtins. The attacker controls only their sandboxed script; the exploit is a single require('child_process').
builtin-child_process-denylist-gap-rce.js
'use strict';
// F-006: vm2 NodeVM DANGEROUS_BUILTINS denylist omits `child_process`.
// The fork's denylist (lib/builtin.js:83-179) blocks host-code-reaching builtins
// even under `builtin:['*']` or explicit naming —…
- Record
GHSA-pq68-rvw4-xp4r- CVSS 3.1
- 10.0 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H - Weakness
- CWE-693, CWE-913
- Updated
- 2026-11-02
OSVCLSA-2026-1791626237 No score
TuxCare security update for vm2 (1 CVE)
TuxCare rebuilt vm2 to address 1 CVE. Fixed in 3.11.7-tuxcare.2.
- Record
CLSA-2026-1791626237- Updated
- 2026-11-02
OSVCLSA-2026-1791666488 No score
TuxCare security update for vm2 (4 CVEs)
TuxCare rebuilt vm2 to address 4 CVEs. Fixed in 3.10.0-tuxcare.7.
- Record
CLSA-2026-1791666488- Updated
- 2026-11-02
OSVCLSA-2026-1791666662 No score
TuxCare security update for vm2 (2 CVEs)
TuxCare rebuilt vm2 to address 2 CVEs. Fixed in 3.11.5-tuxcare.7.
- Record
CLSA-2026-1791666662- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
vm2npm |
through 3.12.0 | 3.12.1 |
vm2TuxCare:npm |
3.11.7-tuxcare.0 up to 3.11.7-tuxcare.2, plus listed versions 3.11.73.11.7-tuxcare.1 |
3.11.7-tuxcare.2 |
vm2TuxCare:npm From an advisory covering 4 CVEs |
3.10.0-tuxcare.0 up to 3.10.0-tuxcare.7, plus listed versions 3.10.03.10.0-tuxcare.13.10.0-tuxcare.23.10.0-tuxcare.33.10.0-tuxcare.43.10.0-tuxcare.53.10.0-tuxcare.6 |
3.10.0-tuxcare.7 |
vm2TuxCare:npm |
3.11.5-tuxcare.0 up to 3.11.5-tuxcare.7, plus listed versions 3.11.53.11.5-tuxcare.13.11.5-tuxcare.23.11.5-tuxcare.33.11.5-tuxcare.43.11.5-tuxcare.53.11.5-tuxcare.6 |
3.11.5-tuxcare.7 |
vm2npm |
before 3.12.1 | 3.12.1 |
History
| Recorded | Changed | Sources |
|---|---|---|
| affected, aliases | ||
| affected, facts | ||
| affected | ||
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-93605 is a critical vulnerability (CVSS 10.0) in Patriksimek Vm2, published September 18, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.48%, the 41st percentile. Fixed in vm2 3.12.1.
References
github.com/patriksimek/vm2/security/advisories/GHSA-pq68-rvw4-xp4r
vulncheck.com/advisories/vm2-nodevm-before-3.12.1-remote-code-execution-via-child-process
nvd.nist.gov/vuln/detail/CVE-2026-93605
github.com/advisories/GHSA-9hxx-m5g2-2q3h
github.com/advisories/GHSA-pq68-rvw4-xp4r
github.com/CVEProject/cvelistV5/tree/main/cves/2026/93xxx/CVE-2026-93605.json
github.com/patriksimek/vm2
Left out here: the rest of 2 source descriptions. The JSON record has them.