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-24120
9.80.08%

CVE-2026-24120: Remote Code Execution via Promise Species Hijacking in vm2 Sandbox

Amit Schendel
Amit Schendel
Senior Security Researcher

May 5, 2026·6 min read·10 visits

PoC Available

Executive Summary (TL;DR)

vm2 prior to version 3.10.5 contains a critical sandbox escape (CVSS 9.8). Attackers bypass internal security wrappers by overwriting Function.prototype.call and hijacking Promise creation, achieving unauthenticated remote code execution on the host system.

An incomplete mitigation for a previous sandbox escape in the vm2 Node.js module allows attackers to execute arbitrary code on the host system. By manipulating Promise species and intercepting internal method calls via prototype pollution, attackers bypass sandbox protections and gain full host access.

Vulnerability Overview

The vm2 package is a widely used Node.js module designed to run untrusted code within an isolated V8 execution context. Versions prior to 3.10.5 contain a critical vulnerability, tracked as CVE-2026-24120, which enables a complete sandbox escape. The vulnerability represents a failure of internal protection mechanisms (CWE-693) leading to arbitrary code injection (CWE-94) on the host system.

The attack surface involves the execution of untrusted JavaScript input within the sandbox environment. The vulnerability specifically targets the Promise resolution mechanism and the internal security wrappers implemented by the package maintainers. Attackers manipulate standard JavaScript built-in objects before the sandbox completes its secure initialization phase.

Successful exploitation results in arbitrary command execution on the host operating system with the privileges of the executing Node.js process. This completely compromises the application relying on the sandbox for security boundary enforcement. Organizations utilizing vm2 for multi-tenant isolation or untrusted code evaluation face immediate risk of host compromise.

Root Cause Analysis

The vulnerability stems from an incomplete patch for CVE-2023-37466, a prior sandbox escape regarding Promise species hijacking. The vm2 security logic attempts to neutralize attacks by resetting the Symbol.species property on the Promise constructor. This reset process relies on JavaScript internal method execution during sandbox setup.

Prior to version 3.10.5, the vm2 wrapper code utilized standard, mutable prototype lookups to execute original Promise methods. Specifically, internal security wrappers for then and catch invoked globalPromiseThen.call(this, ...). This reliance on .call() introduces an exploitable condition if the prototype chain is altered.

An attacker executing code within the sandbox initializes the exploit by overwriting Object.defineProperty with a no-operation function. This neutralization prevents the subsequent vm2 security fixups from correctly applying immutable properties to internal objects. The sandbox environment remains partially initialized and susceptible to further manipulation.

Concurrently, the attacker overrides Function.prototype.call. When the internal vm2 wrapper processes a Promise, it inadvertently routes execution through the attacker-controlled call function. This exposes internal references and allows the V8 engine to resolve the Promise using a malicious constructor defined via Symbol.species.

Code Analysis

Analyzing the setup-sandbox.js file reveals the exact mechanism of the protection failure. The vulnerable implementation binds the execution of wrapped Promise methods using Function.prototype.call. This design incorrectly assumes the integrity of the prototype chain within the sandbox environment during internal wrapper execution.

The following code illustrates the vulnerable implementation alongside the patch introduced in commit 4b009c2d4b1131c01810c1205e641d614c322a29.

// File: lib/setup-sandbox.js
globalPromise.prototype.then = function then(onFulfilled, onRejected) {
    // ...
-   return globalPromiseThen.call(this, onFulfilled, onRejected);
+   return apply(globalPromiseThen, this, [onFulfilled, onRejected]);
};
 
globalPromise.prototype.catch = function _catch(onRejected) {
    // ...
-   return globalPromiseCatch.call(this, onRejected);
+   return apply(globalPromiseCatch, this, [onRejected]);
};

The fix implements a required architectural shift by replacing .call() with a local apply primordial. This apply reference is derived securely from Reflect.apply during the initial environment capture. Capturing the primordial reference early makes the operation immune to runtime prototype pollution.

By utilizing local primordials, the patch severs the internal dependency on the mutable Function.prototype. Attackers modifying Function.prototype.call no longer intercept the internal execution flow of the vm2 wrappers. This closes the specific execution hijack vector utilized in this escape sequence.

Exploitation Mechanism

The exploitation chain requires the attacker to submit a precisely constructed JavaScript payload into the vm2.run() interface. The payload first neutralizes the environment by redefining Object.defineProperty = () => {}. This action stops vm2 from locking down internal object structures during subsequent execution phases.

The attacker proceeds to define a malicious FakePromise constructor and assigns it to p.constructor[Symbol.species]. Simultaneously, the attacker overrides Function.prototype.call. When the sandbox invokes a native Promise operation, the overridden call method intercepts the V8 internal execution flow.

The interception forces the V8 engine's PromiseResolveThenableJob to utilize the attacker's custom constructor. Inside this malicious constructor, the engine passes contextual arguments originating from the host environment. These arguments typically manifest as Error objects or internal stack structures referencing host-level contexts.

The attacker executes prototype climbing on the leaked host object. By accessing err.constructor.constructor, the payload obtains a direct reference to the host environment's Function object. From this access point, Function('return process')() retrieves the Node.js global process object, enabling direct command execution via process.mainModule.require('child_process').execSync().

Impact Assessment

The vulnerability carries a CVSS v3.1 base score of 9.8, categorizing it as Critical severity. The attack vector is entirely network-based, assuming the target application accepts remote input for evaluation within the sandbox. The complexity is low, as reliable and deterministic proof-of-concept payloads exist.

Exploitation requires no authentication and no user interaction. An attacker successfully executing the payload achieves a complete bypass of the intended security boundary. The confidentiality, integrity, and availability impacts are universally high, resulting in total control of the underlying host environment.

The EPSS score stands at 0.00080 (23.22nd percentile), indicating a lower immediate probability of mass exploitation relative to other vulnerabilities. However, the operational impact remains catastrophic for systems relying on vm2 for multi-tenant isolation or untrusted code execution.

While the vulnerability currently shows no known active exploitation in the wild and is absent from the CISA Known Exploited Vulnerabilities (KEV) catalog, the public availability of the exploitation methodology facilitates rapid weaponization by threat actors.

Remediation and Mitigation

The immediate technical mitigation requires upgrading the vm2 package to version 3.10.5. This release integrates the primordial replacements for the internal Promise wrappers. Engineering teams must verify the version update across all dependency trees within their Node.js environments.

The vm2 project is officially deprecated by its maintainers. The inherent architectural limitations of securing the V8 execution context against recursive prototype escapes render long-term maintenance of this model unfeasible. Organizations must treat the 3.10.5 patch strictly as a temporary, stopgap measure.

A permanent remediation strategy requires migrating away from vm2 entirely. Security architectures must transition to isolated processes utilizing strict operating system boundaries. Valid alternatives include WebAssembly runtimes, Docker containers with dropped capabilities, or Firecracker microVMs for robust isolation.

In environments where immediate migration is impossible, network-level monitoring provides secondary defense. Security teams should deploy Endpoint Detection and Response (EDR) signatures monitoring for anomalous child processes spawning from Node.js applications. Specifically, alerts should trigger on sh, bash, or cmd.exe invocations originating from processes handling untrusted input.

Official Patches

patriksimekGitHub Release v3.10.5
GitHub Security AdvisoryOfficial Security Advisory GHSA-qvjj-29qf-hp7p

Fix Analysis (1)

Technical Appendix

CVSS Score
9.8/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
EPSS Probability
0.08%
Top 77% most exploited

Affected Systems

Node.js applications running vm2 versions < 3.10.5

Affected Versions Detail

Product
Affected Versions
Fixed Version
vm2
patriksimek
< 3.10.53.10.5
AttributeDetail
CWE IDCWE-94, CWE-693
Attack VectorNetwork
CVSS Score9.8 (Critical)
EPSS Score0.00080 (23.22%)
Exploit StatusProof of Concept Available
KEV StatusNot Listed

MITRE ATT&CK Mapping

T1190Exploit Public-Facing Application
Initial Access
T1059.004Command and Scripting Interpreter: Unix Shell
Execution
CWE-94
Code Injection

Improper Control of Generation of Code ('Code Injection') via Protection Mechanism Failure

Known Exploits & Detection

Maintainer Test Suite PoCProof of concept verifying interception of internal functions via prototype pollution.

Vulnerability Timeline

Fix for Function.prototype.call interception committed
2026-01-17
Multiple bridge-level hardening commits added to repository
2026-02-15
CVE-2026-24120 formally published
2026-05-04
Technical advisory GHSA-qvjj-29qf-hp7p released
2026-05-04

References & Sources

  • [1]GitHub Release v3.10.5
  • [2]GitHub Security Advisory GHSA-qvjj-29qf-hp7p
  • [3]Fix Commit 4b009c2d4b1131c01810c1205e641d614c322a29
  • [4]Red Hot Cyber - Latest Critical Vulnerabilities Analysis
Related Vulnerabilities
CVE-2023-37466

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.