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



CVE-2026-92949

CVE-2026-92949: Sandbox Escape and State Mutation in vm2 via Accessor Property Descriptor Leak

Amit Schendel
Amit Schendel
Senior Security Researcher

Oct 2, 2026·7 min read·4 visits

Executive Summary (TL;DR)

A security flaw in vm2's proxy bridge allows sandboxed applications to leak and invoke property setters on frozen objects, enabling unauthorized write access to host-realm configurations and bypassing isolation controls.

CVE-2026-92949 is a sandbox bypass vulnerability in the vm2 library affecting versions 3.9.6 through 3.11.6. The flaw exists due to a breakdown in the ReadOnlyHandler proxy boundary, allowing sandboxed scripts to obtain direct references to wrapped property setters on frozen host-bound objects, ultimately leading to unauthorized state modification in the host environment. This security failure violates the read-only contract enforced by the sandbox for frozen/readonly objects, though it does not by itself allow a full execution-level realm escape. Due to systemic and structural design difficulties in securing a shared-runtime JavaScript sandbox, the vm2 library has been officially deprecated.

Vulnerability Overview

The Node.js library vm2 is an advanced sandbox environment designed to run untrusted code securely within a shared V8 process. It relies heavily on V8 Proxies to intercept interactions between the isolated sandbox environment and the main host process. This architecture creates a logical boundary meant to restrict the untrusted code from modifying host-level data structures or escalating privileges.

The vulnerability identified as CVE-2026-92949 undermines this architecture by exposing a weakness in how the proxy bridge handles descriptor requests. When host objects are marked as frozen or read-only, developers expect their attributes to remain completely immutable from within the sandbox. However, the system fails to apply equivalent validation controls on the indirect retrieval pathways of property descriptors, leading to an integrity compromise.

The underlying flaw allows sandboxed code to request property descriptors of immutable host-bound objects and obtain a live, executable proxy wrapper of the underlying setter function. This behavior violates the logical contract enforced by vm2's ReadOnlyHandler proxy. While the bypass does not immediately grant a full execution-level realm escape on its own, it allows attackers to bypass read-only configurations, which frequently serve as a stepping stone to full compromise.

Root Cause Analysis

To understand the root cause, we must analyze the inheritance structure of vm2's proxy handlers. The ReadOnlyHandler class is designed to wrap objects that the application developer wishes to expose inside the sandbox as read-only. This handler intercepts write-traps like set, defineProperty, and deleteProperty to systematically drop or reject write requests. This ensures direct modification of properties on these wrapped objects is blocked.

The vulnerability occurs because ReadOnlyHandler inherits key proxy traps directly from BaseHandler without overriding them. Specifically, the getOwnPropertyDescriptor trap remains unguarded in ReadOnlyHandler. When a sandboxed application requests the descriptor of an accessor property (a property that uses get and set methods) on a frozen host object, BaseHandler processes the query. It returns a descriptor structure where the get and set methods are automatically wrapped in a callable function bridge.

This creates an asymmetric exposure vector. Although direct writes to the proxy are blocked, reading the property descriptor leaks a fully functional, bridge-wrapped wrapper pointing to the original host setter. The sandbox can then invoke this setter directly in the context of the host object, completely bypassing the proxy and its write-restriction traps.

The V8 engine executes the invoked setter on the raw, unwrapped host target. Because the execution path goes straight to the underlying native JavaScript engine, the write-blocking proxy traps are never evaluated. Consequently, the host-realm state is mutated through a view that was explicitly marked as immutable by the developer.

Code Analysis

The vulnerability was resolved in commit d6ef73bd46488102dae8f4bc35f3f3c0eba2ea64 by modifying lib/bridge.js. The fix implements defensive overrides within the proxy handlers to drop setter functions before they are bridged back to the sandbox. Below is a conceptual illustration showing the vulnerable code design versus the patched implementation.

// BEFORE PATCH (lib/bridge.js)
// ReadOnlyHandler did not override getOwnPropertyDescriptorDesc,
// meaning any call to read descriptors would default to BaseHandler.
// BaseHandler returned wrapped accessors (including setters) directly to the sandbox.
class ReadOnlyHandler extends BaseHandler {
    // Missing getOwnPropertyDescriptorDesc override
}

The patch introduces an explicit trap in ReadOnlyHandler to sanitize descriptors before they cross the boundary to the sandbox. When the property descriptor of a frozen host-bound object is queried from the sandbox, the bridge checks if a setter is present and strips it from the returned descriptor.

// AFTER PATCH (lib/bridge.js)
// ReadOnlyHandler is updated to explicitly intercept and sanitize descriptors.
class ReadOnlyHandler extends BaseHandler {
    getOwnPropertyDescriptorDesc(target, prop, desc) {
        validateHandlerTarget(this, target);
        desc = super.getOwnPropertyDescriptorDesc(target, prop, desc);
        
        // Strip the setter if the target is sandbox-bound and holds a set accessor
        if (!isHost && desc && desc.set) {
            desc.set = undefined;
        }
        return desc;
    }
}

Additionally, V8 enforces strict rules regarding proxy behavior. If a target object is frozen, the returned proxy descriptors must align with the target's original attributes. To prevent runtime type errors (TypeError) resulting from the mismatch of stripped setters, the maintainers also updated doPreventExtensions to consistently route descriptor duplication through the new sanitization hook. This ensures V8 internal compliance and prevents application crashes.

Exploitation Methodology

An attacker can exploit this vulnerability using multiple descriptor extraction channels available in standard ECMAScript. These channels include Object.getOwnPropertyDescriptor, Object.getOwnPropertyDescriptors, Reflect.getOwnPropertyDescriptor, and the legacy Object.prototype.__lookupSetter__ function. Each of these APIs triggers the vulnerable getOwnPropertyDescriptor proxy trap under the hood.

// Triggering the exploit inside the sandbox using multiple extraction channels
 
// Channel 1: Using Object.getOwnPropertyDescriptor
const descriptor = Object.getOwnPropertyDescriptor(cfg, 'level');
if (descriptor && descriptor.set) {
    descriptor.set.call(cfg, 'PWNED-gopd');
}
 
// Channel 2: Using the legacy __lookupSetter__ method
const setter = cfg.__lookupSetter__('level');
if (setter) {
    setter.call(cfg, 'PWNED-lookup');
}

Once the setter function is retrieved, the attacker invokes it using Function.prototype.call or Function.prototype.apply. By passing the frozen object as the this argument, the execution runs in the context of the host object. Because the bridge unwraps the proxy context to execute the target function on the native host instance, the mutation happens directly on the host memory space without triggering the set trap.

This execution path requires no authentication or specific privileges inside the sandbox. The only prerequisite is that the host application must expose an object containing accessor properties (getters and setters) to the sandbox, and mark that object as frozen or read-only. If the host application exposes such configurations, the sandbox environment can alter them completely.

Impact Assessment

The impact of CVE-2026-92949 is classified under CWE-471: Modification of Assumed-Immutable Data (MAID). This type of vulnerability compromises the fundamental integrity guarantees provided by a sandbox environment. If an application developer exposes critical configurations, security parameters, database connections, or routing tables as frozen objects, the sandboxed code can alter these parameters to manipulate host application flow.

The National Vulnerability Database has assigned this vulnerability a CVSS v3.1 score of 4.0, reflecting medium severity. The attack complexity is rated as high because the vulnerability requires a specific runtime context: the host must expose an object with accessor properties to the sandbox. The integrity impact is classified as low because the exploit only allows modifications of specific exposed objects, rather than absolute system-level writes or arbitrary host-realm shell execution.

The EPSS score for this vulnerability is 0.00319, which indicates a low immediate probability of active exploitation in the wild. Additionally, the vulnerability is not listed in CISA's Known Exploited Vulnerabilities (KEV) catalog. However, in scenarios where the sandbox is the primary defense line protecting a multitenant execution environment, this bypass represents a severe gap in boundary containment.

Remediation and Migration

The primary mitigation is upgrading vm2 to version 3.11.7 or higher, which contains the complete patch for this flaw. Organizations should audit their dependency trees to identify any transitive usage of vm2 in their environments. Because the library is widely utilized, many security scanners and static analysis tools will flag older installations.

It is critical to note that the vm2 library is officially deprecated and is no longer maintained. Due to the inherent difficulty of securing a shared-process JavaScript runtime, the project maintainers have advised users to migrate away from vm2 completely. The architectural design of Node.js makes it fundamentally difficult to prevent all sandbox escapes when the sandbox and host share a single V8 engine instance.

For robust and secure isolation of untrusted JavaScript code, organizations should migrate to isolated-vm. This library isolates sandboxed execution within separate V8 Isolate contexts, which do not share the same memory heap or garbage collector as the host process. Alternatively, running untrusted code inside microVMs, Docker containers, or WASM runtimes offers far superior hardware-level isolation compared to process-shared JavaScript wrappers.

Official Patches

patriksimekOfficial fix commit introducing ReadOnlyHandler descriptor filtering.

Fix Analysis (1)

Technical Appendix

CVSS Score
4.0/ 10
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:N/I:L/A:N
EPSS Probability
0.32%
Top 78% most exploited

Affected Systems

Node.js applications running vm2 library within multi-tenant execution contexts

Affected Versions Detail

Product
Affected Versions
Fixed Version
vm2
patriksimek
>= 3.9.6, < 3.11.73.11.7
AttributeDetail
CWE IDCWE-471: Modification of Assumed-Immutable Data (MAID)
Attack VectorNetwork / Sandboxed Script Execution
CVSS Score4.0 (Medium)
EPSS Score0.00319 (Percentile: 22.47%)
ImpactLow Integrity (State Modification of Host objects)
Exploit StatusProof of Concept (PoC) Verified
KEV StatusNot Listed

MITRE ATT&CK Mapping

T1068Exploitation for Privilege Escalation
Privilege Escalation
T1211Exploitation for Defense Evasion
Defense Evasion
CWE-471
Modification of Assumed-Immutable Data (MAID)

The product does not protect assumed-immutable data from modification by an unauthorized actor, which can compromise the integrity of the data or system configuration.

Known Exploits & Detection

Official Test SuitesExploitation via Object.getOwnPropertyDescriptor and __lookupSetter__ is verified within unit tests of the fixing commit.

Vulnerability Timeline

Security patch designed and committed by maintainers in d6ef73bd46488102dae8f4bc35f3f3c0eba2ea64.
2026-08-22
CVE-2026-92949 officially assigned and published in the NVD and CVE databases.
2026-09-17
Metadata audit and database record update completed.
2026-09-21

References & Sources

  • [1]Official GitHub Security Advisory (GHSA-633r-hq9m-c4ff)
  • [2]VulnCheck Vulnerability Advisory
  • [3]Official Release tag (v3.11.7)
  • [4]NVD Vulnerability Page
  • [5]CVE.org Official Record

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.

More Reports

•19 minutes ago•CVE-2026-92938
9.9

CVE-2026-92938: Remote Code Execution in vm2 via node:sqlite DatabaseSync Sandbox Escape

CVE-2026-92938 is a critical sandbox escape vulnerability in the vm2 library (versions 3.11.3 through 3.11.6) that allows arbitrary native code execution on the host when the node:sqlite built-in module is loaded inside a sandboxed NodeVM environment.

Amit Schendel
Amit Schendel
2 views•8 min read
•about 1 hour ago•CVE-2026-92937
10.0

CVE-2026-92937: Sandbox Escape leading to Remote Code Execution via Promise Indirection in vm2

CVE-2026-92937 is a critical sandbox escape vulnerability in the `vm2` Node.js library. Due to a logical failure in checking direct invocation targets inside the Proxy bridge, an attacker can register Promise callbacks using `Function.prototype.call` or `Function.prototype.apply` indirection. This bypasses the error sanitization wrappers, delivering raw host error objects directly to sandboxed callbacks and allowing the attacker to escape the sandbox and execute arbitrary shell commands on the host.

Amit Schendel
Amit Schendel
6 views•6 min read
•about 2 hours ago•CVE-2026-92935
9.5

CVE-2026-92935: Remote Code Execution via Array-Shaped Require Config in vm2 NodeVM Sandbox

CVE-2026-92935 is a critical sandbox escape and remote code execution vulnerability in the vm2 library. By supplying an array or exotic object to the require property of NodeVM while nesting is enabled, attackers can bypass security checks, load the host vm2 module, and run arbitrary shell commands on the hosting server.

Alon Barad
Alon Barad
5 views•7 min read
•about 4 hours ago•CVE-2026-92957
9.9

CVE-2026-92957: Sandbox Escape and Remote Code Execution in vm2 via node: Prefix Policy Bypass

A vulnerability in the NodeVM component of the vm2 sandbox package through version 3.11.6 allows sandboxed code to bypass security policies restricting access to built-in modules. When a wildcard require policy is configured with negative deny entries using the 'node:' prefix (e.g., '-node:child_process'), the parser fails to recognize the exemption due to exact string comparison. As a result, the unmitigated module is registered, allowing sandboxed code to import the host child_process module and execute arbitrary system commands.

Alon Barad
Alon Barad
5 views•6 min read
•about 5 hours ago•CVE-2026-92958
8.5

CVE-2026-92958: Built-in Module Denylist Bypass via fs/promises in vm2 NodeVM Subsystem

CVE-2026-92958 is a high-severity sandbox escape and denylist bypass vulnerability within the NodeVM subsystem of the vm2 sandboxing library. When configuring wildcards with negative deny entries, exact-string matches fail to block subpaths like fs/promises. Sandboxed code can import these subpaths to bypass isolation and execute arbitrary filesystem operations on the host.

Amit Schendel
Amit Schendel
6 views•6 min read
•about 6 hours ago•CVE-2026-92951
9.9

CVE-2026-92951: Sandbox Escape via External Package Allowlist Bypass in vm2

An incorrect authorization and directory traversal vulnerability in the vm2 library before version 3.11.7 allows remote attackers to bypass the sandbox's external package allowlist. This flaw permits sandboxed code to resolve and execute arbitrary packages available on the host filesystem under host privileges, leading to unauthenticated sandbox escape and host code execution.

Alon Barad
Alon Barad
6 views•6 min read