Skip to main content
Vulnerability Database/CVE-2026-93603

CVE-2026-93603: vm2 Sandbox Escape RCE Vulnerability

CVE-2026-93603 is a sandbox escape vulnerability in vm2 that enables remote code execution by exploiting improper handling of nullish receivers in non-strict host functions. This article covers technical details, affected versions, and mitigation steps.

Published:

CVE-2026-93603 Overview

CVE-2026-93603 is a sandbox escape vulnerability in the vm2 JavaScript sandbox library through version 3.12.0, fixed in 3.12.1. The flaw resides in the apply trap of the bridge module (lib/bridge.js), which fails to correctly handle a nullish this receiver when sandboxed code invokes a host-provided non-strict function. Untrusted script inside the sandbox can obtain a live proxy of the host realm's global object and execute arbitrary commands on the host through Node.js APIs such as process.getBuiltinModule('child_process').execSync. This defect is classified as Improper Control of Generation of Code [CWE-94].

Critical Impact

Attackers with the ability to run script inside a vm2 sandbox can escape isolation and achieve arbitrary remote code execution on the host process whenever the embedding application exposes any non-strict (sloppy-mode) function.

Affected Products

  • vm2 versions through 3.12.0
  • Applications embedding vm2 that expose non-strict host functions to sandboxed code
  • Node.js services using vm2 for untrusted script evaluation

Discovery Timeline

  • 2026-09-18 - CVE-2026-93603 published to the National Vulnerability Database (NVD)
  • 2026-09-22 - Last updated in NVD database

Technical Details for CVE-2026-93603

Vulnerability Analysis

vm2 mediates every interaction between sandboxed guest code and the host realm through a bridge that wraps host values in Proxy objects. The bridge's apply trap forwards guest-initiated function calls to the underlying host function, translating arguments and receivers across realm boundaries. When the guest calls a host function without a bound receiver, the bridge passes an undefined value straight through to the host invocation. V8 then applies standard non-strict function semantics and substitutes the host realm's global object as this. The bridge subsequently wraps that global and returns the resulting proxy to the sandbox, breaking isolation.

Root Cause

The root cause is missing normalization of a nullish this receiver in lib/bridge.js before crossing the realm boundary. The bridge should have coerced or rejected undefined receivers targeting host callables, but instead relied on JavaScript's implicit this binding, which resolves to the host global in sloppy mode. Strict-mode functions and ES module exports keep this as undefined and are not affected.

Attack Vector

An attacker who controls script executed inside the vm2 sandbox invokes any exposed non-strict host function with no receiver. Suitable call patterns include fn(), a detached method reference, fn.call(), fn.apply(undefined), Reflect.apply(fn, undefined, []), and fn.bind()(). The returned proxy exposes the host process object, from which the attacker reaches child_process and calls execSync to run arbitrary commands. No authentication, user interaction, or network access to the host beyond the sandbox interface is required.

For implementation-level detail, refer to the GitHub Security Advisory GHSA-j89j-5m6r-cr2q and the VulnCheck Advisory on vm2 Sandbox Escape.

Detection Methods for CVE-2026-93603

Indicators of Compromise

  • Unexpected child process creation from the Node.js process embedding vm2, particularly invocations of execSync, exec, spawn, or fork originating from guest workloads.
  • Sandboxed workloads accessing host artifacts such as process.env, process.mainModule, or filesystem paths outside the intended data scope.
  • Outbound network connections initiated by the vm2 host process to attacker-controlled infrastructure shortly after untrusted script evaluation.

Detection Strategies

  • Inventory all Node.js applications and identify direct or transitive dependencies on vm2 at versions at or below 3.12.0 using npm ls vm2 or software composition analysis.
  • Audit host APIs exposed to vm2 sandboxes and flag any non-strict functions that could serve as escape primitives.
  • Instrument the Node.js runtime with async_hooks or process telemetry to alert on unexpected child_process module resolution from sandbox call stacks.

Monitoring Recommendations

  • Forward process creation, network, and file access telemetry from hosts running vm2 workloads to a centralized analytics tier for correlation.
  • Alert on Node.js processes spawning shells (/bin/sh, cmd.exe, powershell.exe) when the parent application does not normally do so.
  • Track EPSS movement for CVE-2026-93603 and correlate with public exploitation reports to prioritize response.

How to Mitigate CVE-2026-93603

Immediate Actions Required

  • Upgrade vm2 to version 3.12.1 or later across all applications and rebuild affected container images.
  • Where upgrade is not immediately possible, remove or refactor host functions exposed to the sandbox so that only strict-mode or ES module functions are reachable.
  • Rotate secrets accessible to any Node.js process that previously evaluated untrusted script through vulnerable vm2 versions.

Patch Information

The maintainers fixed the defect in vm2 3.12.1 by normalizing the receiver in the bridge apply trap so a nullish this no longer resolves to the host global. Consult the GitHub Security Advisory GHSA-j89j-5m6r-cr2q for the authoritative fix reference. Note that the vm2 project has been deprecated by its maintainer; teams should plan migration to an actively maintained isolation mechanism such as isolated-vm or a separate process boundary.

Workarounds

  • Convert all host-exposed callables to strict-mode functions by adding 'use strict' or by shipping them as ES modules, which keeps this as undefined and neutralizes the escape.
  • Wrap every exposed function so it explicitly binds a safe receiver before crossing into the sandbox, for example using Function.prototype.bind with a frozen sentinel object.
  • Run vm2 workloads in a dedicated OS process or container with least-privilege user, seccomp restrictions, and no outbound network access to limit blast radius if escape occurs.
bash
# Upgrade vm2 to the patched release
npm install vm2@3.12.1 --save
npm ls vm2

# Verify no transitive dependency pins an older version
npm audit --production

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.