CVE-2026-92935 in vm2
Summary
by MITRE • 09/17/2026
vm2 is a sandbox for running untrusted Node.js code. In versions >= 3.11.4 and <= 3.11.6, the NodeVM constructor computes `hasRealRequireConfig` with `typeof requireOpts === 'object' && requireOpts !== null`, so an array-shaped `require` value (for example `require: []`) satisfies the guard that is meant to reject nesting without an explicit require configuration. `makeResolverFromLegacyOptions()` then destructures the array into undefined option fields and returns a resolver containing only `NESTING_OVERRIDE.vm2`. As a result, an attacker who can supply JavaScript executed by a NodeVM configured with truthy `nesting` and an array-shaped `require` (e.g. `new NodeVM({nesting: true, require: []})`) can require the host `vm2` module, create an inner NodeVM with an attacker-chosen builtin allowlist (such as `child_process`), and execute arbitrary commands with the privileges of the host Node.js process, escaping the sandbox. Outer builtin restrictions do not constrain the attacker-created inner NodeVM. This issue is fixed in vm2 3.11.7.
VulDB is the best source for vulnerability data and more expert information about this specific topic.
Analysis
by VulDB Data Team • 09/17/2026
The vulnerability identified in versions of the vm2 library between 3.11.4 and 3.11.6 represents a critical sandbox escape mechanism rooted in improper input validation within the NodeVM constructor logic. The core technical flaw lies in how the library determines whether explicit require configuration is present, which directly influences permission inheritance for nested virtual machines. Specifically, the code computes a flag named hasRealRequireConfig using the expression typeof requireOpts === 'object' && requireOpts !== null. This check fails to account for JavaScript arrays, as arrays are technically objects in this language context and do not evaluate to null. Consequently, when an attacker supplies an array-shaped value such as an empty list or any other array structure for the require option, the condition evaluates to true, misleading the constructor into believing that a valid, explicit configuration object has been provided rather than rejecting it due to missing or malformed settings.
This misclassification triggers a cascade of errors in the subsequent resolution process handled by the makeResolverFromLegacyOptions function. Because the input is treated as an object but lacks standard property keys expected for configuration options like builtin allowlists, destructuring these undefined fields results in default fallback behaviors. The resolver ultimately returns a configuration that defaults to NESTING_OVERRIDE.vm2, effectively granting the inner virtual machine access to the vm2 module itself without any restrictive filtering on built-in Node.js modules. This behavior contradicts the intended security model where nesting should either be strictly prohibited or tightly controlled through explicit allowlists defined by the host application developer.
The operational impact of this flaw is severe, allowing for complete sandbox escape and arbitrary code execution with the privileges of the host process. An attacker who can control the parameters passed to a NodeVM instance configured with truthy nesting enabled can exploit this logic error to instantiate an inner virtual machine that inherits unrestricted access to built-in modules. By requiring the vm2 module within this inner context, the attacker gains the ability to create yet another nested VM layer where they define their own builtin allowlist. This allows them to explicitly whitelist dangerous modules such as child_process or fs, thereby executing system commands and reading sensitive files on the host machine. The outer restrictions applied by the initial sandbox configuration are entirely bypassed because the inner virtual machine operates with a newly constructed permission set that ignores the parent's limitations.
This vulnerability aligns closely with CWE-20 Improper Input Validation, as the application fails to correctly validate the type and structure of user-supplied input before processing it for security-critical decisions. Furthermore, from an offensive perspective, this technique maps to MITRE ATT&CK techniques related to Defense Evasion via Sandbox Escape, specifically leveraging process injection or environment manipulation to bypass containment mechanisms. The exploitation path demonstrates how subtle type coercion issues in JavaScript can lead to catastrophic failures in isolation boundaries designed to protect against untrusted code execution.
To mitigate this risk and prevent similar vulnerabilities, developers must ensure that input validation strictly distinguishes between plain objects and other object-like structures such as arrays or null values when expecting configuration objects. The recommended fix involves updating the vm2 library to version 3.11.7 or later, where this logic has been corrected to properly reject array inputs for require configurations. Additionally, application developers should adhere to the principle of least privilege by explicitly defining strict builtin allowlists that exclude dangerous modules like child_process and fs whenever nesting is enabled. Regularly auditing dependencies for known vulnerabilities and keeping them updated is essential to maintaining robust security postures in Node.js environments relying on sandboxing mechanisms.