CVE-2026-92954 in vm2
Summary
by MITRE • 09/17/2026
vm2 is a sandbox library for running untrusted JavaScript in Node.js. In versions >= 3.10.0 and <= 3.11.7, Promises returned from the host realm into the sandbox are not marked as handled at the bridge boundary; only Promises created inside the sandbox are wrapped with a rejection-swallowing handler (lib/setup-sandbox.js), and the bridge only installs host-side rejection sanitizers when sandbox code calls .then/.catch/.finally. As a result, code running in the sandbox can invoke a host function that returns a rejected Promise (for example events.once() exposed via the NodeVM events builtin, or any embedder-provided Promise-returning API) and simply ignore the return value, leaving the host Promise unhandled so that Node.js's default unhandled-rejection behavior terminates the host process. This is an incomplete fix of GHSA-hw58-p9xv-2mjh. The issue is fixed in version 3.11.8.
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 vm2 versions between 3.10.0 and 3.11.7 represents a critical flaw in the isolation mechanisms designed to protect Node.js applications from untrusted JavaScript execution. Vm2 functions as a sandbox library that allows developers to run potentially malicious or untrusted code within an isolated context, preventing direct access to sensitive host resources such as file systems, network interfaces, and environment variables. The core security model relies on strict boundaries between the host realm, where trusted application logic resides, and the sandbox realm, where untrusted code executes. However, a deficiency in how promise objects are managed across this boundary allows an attacker to disrupt the availability of the host process through an unhandled rejection scenario. This issue is classified as CWE-409, which describes the exploitation of unpredictable behavior due to improper handling of unexpected input or state, specifically manifesting here as an incomplete fix for a previously identified security advisory GHSA-hw58-p9xv-2mjh.
The technical root cause lies in the asynchronous bridge mechanism that facilitates communication between the sandbox and the host environment. When code running inside the sandbox invokes a function provided by the host, such as events.once from the NodeVM built-in event module or any custom API exposed to the sandbox, it may receive a Promise object back into its context. In standard JavaScript execution, if a rejected promise is not handled via .then, .catch, or .finally handlers within a reasonable timeframe, the runtime environment triggers an unhandledRejection event. By default in Node.js, this often results in terminating the entire process to prevent silent failures and data corruption. The vm2 library attempted to mitigate this by wrapping promises created inside the sandbox with rejection-swallowing handlers to prevent them from crashing the host if they fail internally. However, the implementation failed to apply similar protection when a promise originates from the host realm and is returned into the sandbox.
This asymmetry in handling creates a specific attack vector where an attacker can exploit this gap by invoking a host function that returns a rejected promise and then deliberately ignoring the return value within the sandbox code. Because the bridge does not install host-side rejection sanitizers for these cross-boundary promises unless explicit handler methods are called, the underlying host promise remains unhandled from Node.js's perspective. Consequently, when the promise rejects, it triggers the default Node.js behavior of terminating the process. This effectively allows a low-privileged attacker running code within the sandbox to achieve a Denial of Service against the entire application hosting the vm2 instance. The impact is severe because it bypasses the primary goal of sandboxing, which is to contain failures and malicious actions without affecting the stability of the host environment.
From an operational perspective, this vulnerability undermines the reliability of any system relying on vm2 for executing untrusted scripts, such as online code editors, automated testing frameworks, or plugin systems that allow user-defined logic. An attacker does not need to escape the sandbox or gain arbitrary code execution privileges; they only need the ability to submit JavaScript snippets that trigger a rejected promise from an exposed host API and neglect to handle it. This makes the vulnerability particularly dangerous in multi-tenant environments where one tenant's malicious script can crash the server for all other users. The lack of explicit handling requirements means that even well-intentioned but poorly written sandbox code could inadvertently cause outages, although intentional exploitation is straightforward given knowledge of exposed APIs like events.once.
To mitigate this vulnerability, organizations must immediately upgrade vm2 to version 3.11.8 or later, where the bridge boundary logic has been corrected to properly handle promises returned from the host realm. For environments that cannot update immediately due to dependency constraints, alternative mitigation strategies include restricting access to APIs known to return promises, such as events.once, or implementing custom wrapper functions in the host code that ensure all returned promises are explicitly handled before being passed into the sandbox. Additionally, developers should review their use of vm2 and consider whether running untrusted JavaScript is strictly necessary; if so, they might evaluate more robust isolation techniques like using separate worker threads with message passing rather than a shared memory sandbox model. Monitoring for process crashes related to unhandled promise rejections can also serve as an early detection mechanism for exploitation attempts in production environments until the patch is applied.