Intelligence
criticalVulnerabilityActive

VM2 Sandbox Escape via Async Generator Type Confusion

VM2 fails to properly isolate host exceptions thrown during async generator cleanup, allowing attackers to break sandbox confinement and execute arbitrary host code. This PoC reliably demonstrates RCE by constructing a type-confused Error object that escapes sandbox restrictions.

S
Sebastion

CVE References

Affected

vm2

Vulnerability Description

VM2 contains a critical sandbox breakout vulnerability rooted in improper exception handling during async generator lifecycle. The flaw exists in how the runtime processes exceptions thrown during the return() method of async generators when combined with yield* expressions. The vulnerability chain exploits a type confusion condition: when an exception originates from host code (outside the sandbox) during generator cleanup, the sandbox's type validation fails to recognize it as a host-originating exception, allowing it to propagate into user code with full host context. This permits attackers to access the constructor.constructor chain and ultimately invoke require() to load child_process module and execute system commands.

PoC Significance

The provided PoC demonstrates reliable, deterministic sandbox escape through a binary search algorithm that narrows the stack depth to trigger the specific exception type confusion condition. The PoC's significance lies in proving that: (1) the vulnerability is reproducible without race conditions, (2) it requires only the ability to execute arbitrary JavaScript inside the VM (the assumed threat model), and (3) full host process access is achievable. The precondition—ability to run code in VM context—is the standard usage pattern, making this highly exploitable in real deployments.

Detection Guidance

Defenders should monitor for: (1) Process creation anomalies from Node.js processes running vm2, especially execSync() or spawn() calls originating from within JS runtime contexts; (2) Stack trace patterns in error logs showing async generator return() methods interleaved with host-level exception frames; (3) Module loading logs detecting dynamic require() of child_process, fs, or os modules from sandboxed contexts; (4) AST analysis of code submitted to vm2 looking for async generator definitions combined with yield*, Symbol.asyncIterator, and .then() patterns. Node.js debug logs with --trace-uncaught will capture the exception boundary crossing.

Mitigation Steps

Immediate actions: (1) Update vm2 to the patched version (verify vendor release); (2) If patching is delayed, disable async generator support via code preprocessing (strip async function* syntax before sandboxing); (3) Apply strict Content Security Policy to code submitted to vm2—reject code containing Symbol.asyncIterator patterns; (4) Run vm2 in isolated worker threads with no access to sensitive modules (remove require entirely if possible); (5) Use OS-level sandboxing (containers, seccomp profiles) as defense-in-depth. Long-term: Evaluate alternative sandboxing solutions (Deno, isolated-vm, native OS sandboxing) for new projects.

Risk Assessment

This vulnerability presents critical exploitation risk because: (1) the attack surface is the default vm2 usage pattern (executing untrusted code), (2) no user interaction is required beyond running sandboxed code, (3) the PoC is deterministic and reliable—not a race condition, (4) exploitation yields complete host compromise (RCE). Threat actors targeting Node.js deployments using vm2 (templating engines, code execution SaaS platforms, educational environments) will prioritize this. Historical data suggests sandbox escapes achieve rapid adoption in exploit kits. Organizations must assume active exploitation is occurring if vm2 processes untrusted code in production.