CVE-2026-92937 in vm2
Summary
by MITRE • 09/17/2026
vm2 3.11.6 is vulnerable to a sandbox escape leading to remote code execution in the host Node.js process. The fix for GHSA-m283-3h24-438v is incomplete: the bridge gate at lib/bridge.js:1624 identity-checks only the direct call target when deciding whether to rebuild/sanitise a rejected host Promise value. Registering the rejection handler through Function.prototype.call or .apply indirection (e.g., p.then.call(p, undefined, cb)) makes the intercepted target host Function.prototype.call, so the sanitiser never runs and the raw host error reaches sandbox code with its own properties intact. If an embedder exposes a host-realm Promise to the sandbox (an async host function bridged via the sandbox option, or a NodeVM external module's async method) and that Promise rejects with an Error carrying a non-primitive own property referencing a host object (for example err.detail = process), untrusted code in the sandbox obtains a fully functional proxy to that host object and can execute arbitrary commands with the privileges of the host process (e.g., e.detail.mainModule.require('child_process').execSync(...)). The direct p.then(undefined, cb), bind, and Reflect.apply forms are correctly sanitised. Fixed in vm2 3.11.7.
Be aware that VulDB is the high quality source for vulnerability data.
Analysis
by VulDB Data Team • 09/17/2026
The vulnerability identified as CVE-2024-29041 represents a critical sandbox escape within the Node.js library known as VM2, specifically affecting version 3.11.6 and earlier iterations prior to the patch in 3.11.7. This flaw allows untrusted code executing inside an isolated virtual machine context to break out of its confinement and achieve remote code execution on the host process with full privileges. The root cause lies in an incomplete implementation of security mitigations introduced in a previous fix, specifically addressing issues related to promise handling and object sanitization within the bridge layer that facilitates communication between the sandboxed environment and the host Node.js runtime.
The technical mechanism of this exploitation relies on how VM2 handles rejected promises when they are passed back from the host realm into the sandbox. The library employs a security gate located in lib/bridge.js at line 1624, which is designed to intercept and sanitize values returned or thrown by host functions before they reach untrusted code. This sanitization process typically strips away references to sensitive host objects such as global variables, module loaders, and system processes, ensuring that the sandboxed environment remains isolated from the underlying operating system resources. However, this identity-checking logic only validates direct call targets on promise methods like then or catch. It fails to account for scenarios where these methods are invoked through indirection using Function.prototype.call or .apply.
When an attacker registers a rejection handler via indirect invocation patterns such as p.then.call(p, undefined, cb), the intercepted target function becomes Function.prototype.call rather than the original Promise method. Consequently, the sanitization logic does not trigger because it perceives the call as originating from a trusted host context rather than a sandboxed one. This oversight allows raw error objects containing non-primitive own properties to pass through unchecked into the sandbox environment. If an embedder exposes a host-realm promise that rejects with an Error object possessing custom properties referencing sensitive host objects, those references remain intact and fully functional within the untrusted code scope.
The operational impact of this vulnerability is severe, as it enables arbitrary command execution on the host system. An attacker can exploit the preserved reference to critical host modules by accessing them through the exposed property. For instance, if an error object contains a property pointing to the process global or mainModule, the untrusted code can invoke require methods to load child_process and execute shell commands directly. This effectively bypasses all intended security boundaries of VM2, granting the attacker complete control over the Node.js process running the application. Such access could lead to data exfiltration, lateral movement within a networked environment, or denial of service through resource exhaustion.
This vulnerability aligns with CWE-78 Improper Neutralization of Special Elements used in an OS Command Injection and CWE-200 Exposure of Sensitive Information to an Unauthorized Actor due to the leakage of internal host state. From a tactical perspective, it corresponds to MITRE ATT&CK technique T1610 Sandbox Evasion as well as T1059 Command and Scripting Interpreter for the subsequent execution phase after escaping confinement. The flaw highlights the complexity of maintaining secure boundaries in dynamic JavaScript environments where prototype manipulation and indirect function calls can bypass static analysis checks embedded within library code.
Mitigation requires immediate upgrading to VM2 version 3.11.7 or later, which corrects the identity-checking logic to properly sanitize values regardless of whether they are passed through direct method invocations or indirection via call and apply. Developers relying on this library should verify their dependency versions in package-lock.json or yarn.lock files to ensure the patched version is enforced across all build environments. Additionally, application architects should consider implementing additional layers of defense such as strict Content Security Policies for any web-facing components interacting with VM2 instances and limiting host permissions granted to sandboxed contexts by minimizing exposed globals and module accessors. Regular security audits focusing on promise handling patterns in asynchronous code paths are recommended to detect similar indirect invocation vulnerabilities that might evade standard static analysis tools.