CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-2CM2-M3W5-GP2F
10.0

GHSA-2CM2-M3W5-GP2F: Remote Code Execution via Transformer Bypass in vm2

Amit Schendel
Amit Schendel
Senior Security Researcher

May 8, 2026·8 min read·6 visits

PoC Available

Executive Summary (TL;DR)

A critical sandbox escape vulnerability in the vm2 library allows attackers to execute arbitrary code on the host system. The flaw exists in the Transformer component, which fails to correctly secure computed-key access on objects with custom prototypes. Exploitation yields full unauthenticated Remote Code Execution.

The vm2 package for Node.js provides a software-based sandbox for untrusted code execution. Vulnerability GHSA-2CM2-M3W5-GP2F enables an attacker to bypass these sandbox protections via the Transformer component. The issue resides in the parsing logic responsible for intercepting JavaScript property access. Attackers leverage custom prototypes and computed keys to expose the internal sandbox state mechanism, leading to full host compromise.

Vulnerability Overview

The vm2 library operates as a software-level sandbox within Node.js, designed to execute untrusted JavaScript code securely. It achieves this by combining the native Node.js vm module with Proxy objects and Abstract Syntax Tree (AST) rewriting. The AST rewriting component, known as the Transformer, modifies the untrusted code before execution to enforce security boundaries. This transformation ensures that potentially dangerous operations are intercepted and redirected through a secure bridge.

The vulnerability identified as GHSA-2CM2-M3W5-GP2F represents a severe failure in this protection mechanism. The flaw resides specifically within the Transformer logic responsible for evaluating and rewriting property access expressions. The sandbox relies on an internally maintained state object to manage the secure bridge and exception handling. This object is intentionally obfuscated and assigned the variable name VM2_INTERNAL_STATE_DO_NOT_USE_OR_PROGRAM_WILL_FAIL.

An attacker can construct a specific JavaScript payload that evades the AST rewriting process. This evasion occurs when the payload utilizes computed-key property access on an object equipped with a custom prototype. By bypassing the transformer, the sandboxed code gains direct access to the internal state variable. This access represents a complete sandbox escape, granting the untrusted code the ability to manipulate host execution contexts.

The impact of this vulnerability is critical. Successful exploitation yields Remote Code Execution (RCE) on the underlying host operating system. The execution occurs with the privileges of the Node.js process running the vm2 sandbox. This allows the attacker to interact with the host file system, execute arbitrary shell commands, and pivot to other systems on the network.

Root Cause Analysis

The root cause of GHSA-2CM2-M3W5-GP2F is an improper implementation of AST transformation logic within the Transformer component. The Transformer parses incoming JavaScript and rewrites nodes to intercept property accesses. When sandboxed code attempts to access a property, the transformer typically wraps the expression in a validation function. This validation ensures the property does not resolve to sensitive host objects.

To optimize performance, vm2 implements a "fast-path" within the transformer. This fast-path attempts to bypass the expensive validation wrapper for operations deemed statically safe. The fast-path logic evaluates the type of property access being performed. If the access uses a computed key, such as object[key], the static analyzer faces challenges in determining the final property name at compile time.

The vulnerability manifests because the fast-path logic fails to account for objects with custom prototypes. When a computed key is evaluated against an object that inherits from a modified prototype chain, the transformer's static safety assumptions are violated. The transformer incorrectly assumes the access is safe and permits the un-wrapped execution of the expression.

This logical flaw allows the attacker to compute a reference to the VM2_INTERNAL_STATE_DO_NOT_USE_OR_PROGRAM_WILL_FAIL variable. Because the transformer skipped the wrapping process due to the prototype condition, the property lookup resolves directly to the internal state object. The attacker leverages this exposed reference to interact directly with the sandbox's core management interface.

Code Analysis and Transformation Bypass

The execution model of vm2 heavily relies on modifying the abstract syntax tree of user-supplied code. The AST parser traverses the tree looking for MemberExpression nodes. A MemberExpression represents object property access, which is the primary vector for escaping a JavaScript sandbox. The transformer must correctly identify and sanitize every instance of property access.

// Conceptual representation of the vulnerable fast-path logic
function transformMemberExpression(node) {
    if (node.computed) {
        // The logic fails to check the prototype chain of the base object
        if (isAssumedSafeObject(node.object)) {
            return node; // Bypass wrapper, return un-modified node
        }
    }
    return wrapInSecureBridge(node);
}

In the vulnerable state, the isAssumedSafeObject logic does not verify if the object has been manipulated via __proto__ or Object.setPrototypeOf. By supplying a custom prototype, the attacker forces the object to pass the static analysis check. The returned node is executed without the wrapInSecureBridge protection. This allows the direct resolution of the internal string identifier.

// Conceptual representation of the patched logic
function transformMemberExpression(node) {
    if (node.computed) {
        // The patch removes the unsafe fast-path for computed properties
        // All computed property access is strictly forced through the bridge
        return wrapInSecureBridge(node);
    }
    return wrapInSecureBridge(node);
}

The fix implemented in vm2 version 3.11.2 modifies the AST rewriting engine. The patch eliminates the insecure fast-path for computed keys associated with complex objects. By forcing all computed property accesses through the proxy bridge, the sandbox ensures that any reference to VM2_INTERNAL_STATE_DO_NOT_USE_OR_PROGRAM_WILL_FAIL is intercepted. The bridge enforces a strict blocklist, preventing the sandboxed context from resolving the internal state variable.

Exploitation Methodology

Exploiting this vulnerability requires the attacker to supply a crafted JavaScript payload to an application utilizing vm2. The attack chain consists of four distinct phases. The first phase involves defining a custom prototype designed to manipulate the property resolution behavior of the JavaScript engine. This prototype acts as the foundation for the transformer bypass.

The second phase executes the computed key access. The attacker instantiates an object inheriting the malicious prototype. They then perform a property lookup using a dynamically generated key. This key resolves to the string value VM2_INTERNAL_STATE_DO_NOT_USE_OR_PROGRAM_WILL_FAIL. Because the transformer misclassifies the object due to its prototype, the execution proceeds unmodified.

In the third phase, the JavaScript engine evaluates the un-wrapped expression and returns the internal state object. This object contains references to the host environment's execution context, including un-sandboxed catch handlers and the bridge mechanism itself. The attacker stores a reference to this object within the sandboxed environment.

The final phase achieves remote code execution. The attacker utilizes the internal state object to hook an exception handler or directly access the host's global object. By calling the standard Node.js require function through the host context, the attacker imports the child_process module. This module provides the execSync function, enabling the execution of arbitrary operating system commands.

Impact Assessment

The impact of a successful sandbox escape in a Node.js environment is absolute. Applications utilizing vm2 often do so to execute untrusted code submitted by end-users. This includes serverless function execution platforms, dynamic configuration evaluators, and online IDEs. When the sandbox is broken, the untrusted code executes with the full privileges of the host application.

The confidentiality impact is high. The attacker gains read access to all environment variables, which frequently contain sensitive credentials, API keys, and database connection strings. The attacker can read any file on the local file system accessible by the Node.js user. This permits the extraction of proprietary source code or user data.

The integrity and availability impacts are equally severe. The attacker can modify application binaries, alter configuration files, or implant persistent backdoors. The execution of arbitrary operating system commands allows the attacker to terminate critical processes, consume system resources, or participate in distributed denial-of-service attacks. The compromised host can also be utilized as a pivot point to attack internal network infrastructure.

Remediation and Mitigation

The immediate remediation strategy requires upgrading the vm2 package to version 3.11.2. This version contains the logic modifications to the AST transformer necessary to prevent the fast-path bypass. Package managers should be audited to ensure no transitive dependencies are relying on vulnerable versions of vm2.

The strategic, long-term recommendation is to migrate entirely away from the vm2 library. The maintainers have officially deprecated the project due to the architectural limitations of implementing software-based sandboxes via AST rewriting. The persistent discovery of bypass vulnerabilities indicates that the fundamental design is fragile. Development teams must evaluate alternatives for secure code execution.

The industry standard replacement for Node.js sandboxing is isolated-vm. This library leverages native V8 engine isolates rather than relying on software-level proxy objects and code rewriting. V8 isolates provide robust, hardware-enforced memory separation. Migrating to isolated-vm eliminates the entire class of AST transformer bypass vulnerabilities.

For systems unable to immediately migrate, security teams should implement Web Application Firewall (WAF) or Intrusion Detection System (IDS) rules. Detection should focus on identifying the string VM2_INTERNAL_STATE_DO_NOT_USE_OR_PROGRAM_WILL_FAIL within incoming web requests or untrusted data sources. This variable is an internal constant and its presence in user input is a definitive indicator of an attempted vm2 exploit.

Official Patches

vm2 MaintainersGitHub Release: vm2 v3.11.2

Technical Appendix

CVSS Score
10.0/ 10

Affected Systems

Node.js applications processing untrusted JavaScript using vm2 versions < 3.11.2Serverless platforms relying on vm2 for tenant isolationDynamic configuration systems evaluating user-provided scripts via vm2

Affected Versions Detail

Product
Affected Versions
Fixed Version
vm2
npm
< 3.11.23.11.2
AttributeDetail
CWE IDCWE-693: Protection Mechanism Failure
Attack VectorNetwork / Untrusted Input
CVSS Score10.0 (Critical)
ImpactUnauthenticated Remote Code Execution (RCE)
Exploit StatusProof of Concept Available
KEV StatusNot Listed

MITRE ATT&CK Mapping

T1211Exploitation for Privilege Escalation
Privilege Escalation
T1059.003Command and Scripting Interpreter: Windows Command Shell
Execution
T1059.004Command and Scripting Interpreter: Unix Shell
Execution
CWE-693
Protection Mechanism Failure

Failure to properly enforce software-defined sandbox boundaries during property evaluation.

References & Sources

  • [1]GitHub Advisory: GHSA-2CM2-M3W5-GP2F
  • [2]NPM Package: vm2
  • [3]GitLab Advisory Database (GLAD) entry for vm2

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.