A batch of twelve critical security vulnerabilities has been disclosed in vm2, the popular Node.js sandboxing library used to execute untrusted JavaScript code in isolation. The CVEs — several rated CVSS 10.0, the maximum possible score — allow attackers to escape the sandbox boundary and execute arbitrary commands on the host operating system. With over one million weekly downloads and 885 direct dependents on npm, the exposure is significant. The safe version is 3.11.2; anything older is vulnerable to at least one of these flaws.
vm2 Sandbox Escape: Technical Details
vm2 is an open-source Node.js library that provides a sandboxed execution environment for running untrusted JavaScript — code that an application does not control or fully trust, such as user-supplied scripts, plugins, or dynamically loaded modules. vm2 intercepts and proxies JavaScript objects at the runtime level to prevent sandboxed code from accessing host-side resources like the file system, child processes, or network APIs.
A sandbox escape (a class of vulnerability where code running inside an isolated execution environment breaks out of that environment and gains access to the host system's full capabilities) in a library like vm2 is a critical failure: the entire security value proposition of the library is its ability to contain untrusted code. When the sandbox is broken, an attacker's JavaScript gains the same access as the Node.js process itself — potentially including file system reads, command execution, and network access.
The twelve vulnerabilities disclosed span multiple technical root causes, each bypassing vm2's object proxying and interception mechanisms through different JavaScript language features. Here is the full list:
| CVE | CVSS | Root Cause | Patched In | |—–|——|———–|———–| | CVE-2026-22709 | 9.8 | Async function Promise callback bypass | 3.10.2 | | CVE-2026-24118 | 9.8 | __lookupGetter__ sandbox escape | 3.11.0 | | CVE-2026-24120 | 9.8 | Promise species hijacking (bypass of CVE-2023-37466 patch) | 3.11.0 | | CVE-2026-24781 | 9.8 | inspect function escape | 3.11.0 | | CVE-2026-26332 | 9.8 | SuppressedError escape | 3.11.0 | | CVE-2026-26956 | 9.8 | WebAssembly exception handling / TypeError via Symbol-to-string | 3.10.5 | | CVE-2026-43997 | 10.0 | Code injection via host Object acquisition | 3.11.0 | | CVE-2026-43999 | 9.9 | Allowlist bypass to load child_process builtin | 3.11.0 | | CVE-2026-44005 | 10.0 | Prototype pollution enabling sandbox escape | 3.11.0 | | CVE-2026-44006 | 10.0 | Code injection via BaseHandler.getPrototypeOf | 3.11.0 | | CVE-2026-44007 | 9.1 | Improper access control allowing OS command execution | 3.11.1 | | CVE-2026-44009 | 9.8 | Null prototype exception escape | 3.11.2 |
The CVSS v3.1 vector for the representative flaw CVE-2026-22709 is AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H — meaning it is network-exploitable (AV:N), requires low complexity (AC:L), no privileges (PR:N), no user interaction (UI:N), and produces full confidentiality, integrity, and availability impact (C:H/I:H/A:H). That combination produces the 9.8 Critical rating. The three CVSS 10.0 CVEs share the same attack vector profile but also have a Changed scope component, meaning exploitation can affect resources beyond the immediate vulnerable component.
The deepest technical root cause across these CVEs is that vm2's security model is built on top of JavaScript's own object interception mechanisms — Proxy objects, prototype chain inspection, and Reflect APIs. These are the same mechanisms that JavaScript engines use to implement the language's own runtime behaviour. Researchers have repeatedly demonstrated that any sandbox built entirely in JavaScript is inherently fragile: a sufficiently skilled attacker who understands V8 internals, WebAssembly exception semantics, or Promise scheduling can find paths through the interception layer. CVE-2026-26956 is a direct illustration — it uses WebAssembly exception handling (a low-level feature processed inside Google's V8 engine before JavaScript-level interception can fire) to surface a TypeError that propagates back into sandboxed code without being sanitised by vm2's proxy layer.
Exploitation Status and Threat Landscape
Public PoC (Proof-of-Concept — working exploit code shared openly that anyone can use to reproduce or weaponise the vulnerability) code has been confirmed for CVE-2026-22709 and CVE-2026-26956. The maintainer of vm2 himself noted that CVE-2026-22709 is "trivial to exploit" in affected versions. Penligent's analysis provides a detailed deconstruction of the exploit chain, and a PoC is also hosted as a public GitHub Gist.
Aviatrix's threat research documents a confirmed supply chain exploitation scenario: attackers exploited a critical vm2 sandbox escape (CVE-2026-22709) to gain initial foothold via a vulnerable application that used vm2 to execute user-supplied scripts. From that foothold they achieved privilege escalation on the underlying OS. This is the canonical supply chain risk model: a developer adds vm2 as a trusted dependency to safely run untrusted code, and the library itself becomes the attack vector.
MITRE ATT&CK technique T1059.007 — Command and Scripting Interpreter: JavaScript covers the initial sandbox escape. Downstream privilege escalation and lateral movement map to T1068 — Exploitation for Privilege Escalation and T1195 — Supply Chain Compromise when the vulnerable library is embedded in a distributed application or platform.
Who Is Affected
Any Node.js application that uses vm2 to execute untrusted JavaScript is affected. This includes:
- SaaS platforms that allow users to write and execute custom scripts or automation rules
- CI/CD systems that run user-supplied build scripts inside a Node.js runner
- IDE extensions and code editors that use vm2 for plugin sandboxing
- API gateways and serverless platforms that execute user-provided middleware or transformation logic
- Security tools that parse or execute JavaScript payloads in an isolated context
The npm ecosystem figures are stark: vm2 has over one million weekly downloads and 885 direct package dependents as of the disclosure date. Transitive dependents — packages that depend on packages that depend on vm2 — number in the thousands. Many applications may be running vm2 without their developers being aware of it as a transitive dependency.
All versions below 3.11.2 are vulnerable to at least one of the twelve CVEs. Versions below 3.10.2 are vulnerable to CVE-2026-22709 (the most publicly documented). Versions 3.10.2 through 3.10.4 are vulnerable to CVE-2026-26956. Versions 3.10.5 through 3.11.1 are vulnerable to CVE-2026-44007 and CVE-2026-44009.
What You Should Do Right Now
- Audit your dependency tree. Run the following command in your Node.js project root to identify all installed versions of vm2, including transitive dependencies:
npm ls vm2
# or
npx npm-check-updates --filter vm2
- Upgrade to vm2 3.11.2 immediately. This is the only version in which all twelve CVEs are patched:
npm install vm2@3.11.2
# or with yarn
yarn add vm2@3.11.2
- Evaluate migrating away from vm2 entirely. The project was deprecated in July 2023 — before being resurrected in October 2025 — precisely because its pure-JavaScript sandbox model is fundamentally difficult to secure. Even at 3.11.2, the attack surface remains because the sandbox is built on top of language mechanisms that were not designed as a security boundary. The maintainers themselves recommend isolated-vm as the successor library. isolated-vm uses V8's native Isolate interface — a true hardware-enforced isolation boundary inside the JavaScript engine — which provides a more robust foundation than JavaScript-level proxy interception.
- For maximum isolation, use OS-level containerisation. If your threat model treats executed code as fully untrusted (arbitrary user-supplied code), neither vm2 nor isolated-vm alone is sufficient. Use Docker or another container runtime with a minimal attack surface, seccomp profiles, and no-new-privileges flags to impose OS-level isolation in addition to any JavaScript-level sandbox.
- Check for exploitation indicators. If you are running a vm2-based service exposed to user input, review application logs for unexpected child process spawning, file system access outside expected paths, or outbound network connections initiated by the sandbox worker process. Look for patterns consistent with
child_process.execcalls orfsmodule access that your application should not be making.
- Pin and lock your dependency versions. Use
package-lock.jsonoryarn.lockand enforce version pinning in CI to prevent automatic upgrade to vulnerable transitive versions when parent packages update.
Background: Understanding the Risk
The history of vm2 is a case study in the fundamental challenge of building secure sandboxes in JavaScript. The library has been exploited repeatedly since at least 2023, when the original maintainer deprecated the project after CVE-2023-29017 (another critical sandbox escape). The pattern is consistent: researchers find a new JavaScript engine feature or edge case in the object model that vm2's proxy interception does not handle, and the sandbox breaks.
This is not a flaw unique to vm2 — it is inherent to the architecture. JavaScript was designed as a single-threaded, dynamically-typed scripting language with pervasive reflection capabilities. The same features that make JavaScript powerful (Proxy objects, prototype chain manipulation, Symbol-to-string coercion, WeakRef finalisation, WebAssembly exception semantics) are the features that sandbox escape researchers exploit. Building a security boundary on top of a language that was never designed to enforce one is structurally difficult.
The resurrection of the project in October 2025 was accompanied by a commitment to patch all outstanding vulnerabilities and eventually rewrite the codebase in TypeScript. The twelve CVEs in this disclosure represent the backlog of vulnerabilities accumulated since the deprecation. The fact that three CVEs carry CVSS 10.0 — the highest possible score — and that PoC code is publicly available for at least two of them means the window between disclosure and weaponisation is effectively closed for any application still running a pre-3.11.2 version.
For organisations evaluating their JavaScript execution strategy, the Semgrep analysis of vm2's sandbox model and the Endor Labs breakdown of CVE-2026-22709 provide clear technical rationale for why isolated-vm or OS-level containerisation should be the preferred architecture going forward.
Conclusion
The twelve vm2 CVEs disclosed today — including three rated CVSS 10.0 and two with public PoC code — make a clear operational case: upgrade to 3.11.2 immediately, then plan migration to isolated-vm or container-based isolation for any service that executes untrusted code. For applications already exposed to user-supplied JavaScript input, review logs for post-exploitation indicators and treat any anomalous process or network activity from the vm2 worker as a potential indicator of compromise.
For any query contact us at contact@cipherssecurity.com

