Security Alert: Dozen Critical Vulnerabilities Found in vm2 Node.js Library – Sandbox Escapes Allow Host Takeover

The CyberSec Guru

Critical vm2 Sandbox Vulnerabilities

If you like this post, then please share it:

Buy me A Coffee!

Support The CyberSec Guru’s Mission

🔐 Fuel the cybersecurity crusade by buying me a coffee! Why your support matters: Zero paywalls: Keep the main content 100% free for learners worldwide, Writeup Access: Get complete in-depth writeup with scripts access within 12 hours of machine drop.

“Your coffee keeps the servers running and the knowledge flowing in our fight against cybercrime.”☕ Support My Work

Buy Me a Coffee Button

If your Node.js application runs user-supplied code through vm2, stop reading and go check your version number. Eleven new critical vulnerabilities have been disclosed in the library, with CVSS scores reaching 10.0, all affecting versions up to 3.11.1 and patched only in 3.11.2. The attack path in each case is the same: an attacker escapes the sandbox and runs arbitrary code on your host. Two of the eleven remain completely unpatched as of this writing.

VM2 Logo
VM2 Logo

What vm2 is supposed to do

vm2 is a Node.js library designed to run untrusted JavaScript in an isolated container. It works by intercepting and proxying JavaScript objects sitting between sandboxed code and the host environment, blocking access to sensitive APIs like process, child_process, and the filesystem. It’s used across more than 200,000 GitHub projects and sees roughly one million weekly npm downloads, powering everything from online coding platforms and CI pipelines to low-code automation tools and multi-tenant SaaS apps.

The library’s core security promise that code inside a VM instance cannot reach the host system has now been broken across eleven distinct techniques.

The history nobody wants to acknowledge

This isn’t a first offense. vm2 has been hit by sandbox escapes before: CVE-2022-36067, CVE-2023-29017, CVE-2023-29199, CVE-2023-30547, CVE-2023-32314, CVE-2023-37466, and CVE-2023-37903. That last one, discovered in July 2023, was severe enough that maintainer Patrik Simek announced the project would be discontinued. Those discontinuation notices were quietly removed from the README after the project was revived in late 2025, and the security page was updated in October 2025 to state that vm2 3.x versions are being actively maintained.

Then January 2026 arrived. CVE-2026-22709 (CVSS 9.8) was disclosed, enabling sandbox escape via manipulation of Promise.prototype.then and Promise.prototype.catch. That was patched. Now, four months later, there are eleven more.

What’s actually happening – The technical breakdown

All eleven vulnerabilities share a common root problem: vm2’s security model is built entirely on JavaScript-level proxy wrapping, and JavaScript keeps finding ways around itself.

The Promise bypass (CVE-2026-22709)

CVE-2026-22709 allows attackers to bypass Promise callback sanitization and execute arbitrary code outside sandbox boundaries. The CVSS vector – AV:N/AC:L/PR:N/UI:N means it’s network-exploitable, low complexity, requires no authentication, and no user interaction. In practical terms: if an attacker can execute code inside a vm2 sandbox, this flaw gives them a path to run commands directly on the underlying system.

The WASM bypass (CVE-2026-26956)

CVE-2026-26956 targets Node.js v25 using a WebAssembly try_table instruction that bypasses vm2’s sanitization entirely. Researchers demonstrated full root-level code execution through this technique. Here’s why this one is interesting from a design standpoint: vm2 wraps JavaScript objects with proxies to intercept access attempts. But WASM exception handling runs at the V8 engine level, below those proxies. By triggering a TypeError through Symbol-to-string coercion inside a WASM exception handler, an attacker can get a raw, unwrapped host-side error object to leak back into the sandbox. From there, walking the constructor chain up to the host’s process object is a known technique. Once you have process, you have the host.

__lookupGetter__ and util.inspect (CVE-2026-24118 and CVE-2026-24781)

These two show how ordinary, legitimate-looking JavaScript methods become attack vectors. CVE-2026-24118 exploits __lookupGetter__ behavior to escape the sandbox, while CVE-2026-24781 abuses Node.js’ util.inspect module internals to expose raw host objects and bypass vm2’s proxy isolation layer. Neither of these is an obscure or deprecated function, they’re the kind of thing sandboxed scripts might realistically call, which is exactly what makes them hard to block without breaking legitimate use cases.

New JavaScript features, new attack paths (CVE-2026-26332)

CVE-2026-26332 leverages DisposableStack and SuppressedError mechanics introduced in Node.js v24 to expose the host Function object. This is a pattern we’ve seen with vm2 before: every time JavaScript evolves as a language and Node.js adds new built-ins, it potentially introduces new surface area that vm2’s proxy model doesn’t yet account for.

Module loading bypass (CVE-2026-43999)

CVE-2026-43999 bypasses vm2’s built-in module allowlist using Module._load(), even when child_process is explicitly blocked. This one matters because many deployments rely on the allowlist as their primary control. Blocking child_process and calling it done is a common configuration. This CVE makes that configuration worthless.

Prototype pollution at scale (CVE-2026-44005)

CVE-2026-44005 allows attackers to modify shared host prototypes – Object.prototype and Function.prototype – potentially corrupting the entire Node.js process. This goes beyond the sandbox. Prototype pollution at Object.prototype in a shared process means the attacker isn’t just escaping their VM, they’re potentially affecting every other tenant or operation running in the same Node process.

The configuration trap (GHSA-8hg8-63c5-gwmx)

A dangerous configuration flaw revealed that enabling nesting: true effectively defeats require: false, allowing sandboxed code to create unrestricted inner VMs and achieve full RCE despite security restrictions being in place. This one isn’t a bug in the traditional sense – it’s a configuration interaction that nobody documented as dangerous. Many operators enabling nested VM support probably had no idea they were disabling their module restrictions.

The two unpatched flaws

CVE-2026-44008 and CVE-2026-44009 remain unpatched in versions up to 3.11.1. These flaws exploit how array species are handled and exception logic to expose host-side objects and regain unrestricted access to the host Function constructor.

Why this matters beyond your own infrastructure

vm2 is the engine under the hood of a lot of platforms where “run this user’s script” is a core feature. The threat model here isn’t an internal developer making a mistake. It’s a malicious user on a multi-tenant platform who knows exactly what they’re doing – submitting a script that looks benign, triggering one of these vectors, and pivoting from “script execution” to “full server access.” With code execution on the underlying OS, the follow-on attacks are standard playbook: privilege escalation, lateral movement within cloud or container environments, command-and-control establishment, and data exfiltration via encrypted tunnels.

Proof-of-concept code is already public

In previous vm2 vulnerabilities, public exploits were released shortly after disclosure, increasing real-world risk for organizations relying on the library. There’s no confirmed in-the-wild exploitation yet and no CISA KEV catalog entry at time of writing but that can change quickly once PoC code circulates. Don’t use “no confirmed exploitation” as a reason to delay remediation.

What to do

Update to vm2 3.11.2. All currently disclosed flaws are patched in that version.

Note, though, that patching individual functions won’t work as a workaround. The combination of vectors Symbol coercion, Promise callbacks, WASM exception handling, __lookupGetter__, util.inspect, module loading, prototype pollution, configuration interactions means there’s no surgical fix short of the full upgrade.

For higher-risk deployments, security researchers recommend moving untrusted code execution off library-level sandboxing entirely and into isolated Linux containers (LXC) or lightweight VMs like Firecracker MicroVMs. That’s a bigger architectural lift, but the pattern is now clear: vm2’s sandbox escapes have been occurring since 2022, and each JavaScript language update creates new attack surface the library can’t anticipate.

The longer view

Simek has acknowledged this openly that new bypasses will likely keep emerging. That’s not a knock on the maintainer; it’s an honest assessment of what JavaScript sandboxing via JavaScript can and can’t do. The V8 engine is extraordinarily complex, the language keeps evolving, and any security boundary built on top of that language is operating on unstable ground.

The question organizations need to ask isn’t just “are we on 3.11.2?” It’s “should we still be relying on vm2 as our isolation boundary at all?”

FAQ

Do I need to be on Node.js 25 to be vulnerable? Only CVE-2026-26956 specifically requires Node.js 25 and WASM exception handling. The majority of these CVEs affect earlier versions. Update regardless of your Node version.

Can I block specific functions as a workaround? No. The range of attack vectors is too wide. Blocking child_process doesn’t close the __lookupGetter__ path. Disabling nesting doesn’t fix the WASM issue. There’s no configuration combination that addresses all eleven.

Is there a drop-in replacement for vm2? Not really, which is part of why vm2 remained in production at so many organizations even after its 2023 discontinuation. Alternatives like isolated-vm exist and offer stronger isolation (native C++ extension, no JavaScript boundary), but they require migration work and aren’t always drop-in compatible.

Buy me A Coffee!

Support The CyberSec Guru’s Mission

🔐 Fuel the cybersecurity crusade by buying me a coffee! Your contribution powers free tutorials, hands-on labs, and security resources.

Why your support matters:
  • Writeup Access: Get complete writeup access within 12 hours
  • Zero paywalls: Keep the main content 100% free for learners worldwide

Perks for one-time supporters:
☕️ $5: Shoutout in Buy Me a Coffee
🛡️ $8: Fast-track Access to Live Webinars
💻 $10: Vote on future tutorial topics + exclusive AMA access

“Your coffee keeps the servers running and the knowledge flowing in our fight against cybercrime.”☕ Support My Work

Buy Me a Coffee Button

If you like this post, then please share it:

News

Discover more from The CyberSec Guru

Subscribe to get the latest posts sent to your email!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Discover more from The CyberSec Guru

Subscribe now to keep reading and get access to the full archive.

Continue reading