Executive brief
vm2 is a JavaScript sandbox used to safely execute untrusted code with restricted capabilities. When the allowAsync option is set to false to prevent asynchronous code execution, an attacker can bypass this restriction using Promise static methods, allowing malicious code to continue executing after the sandbox returns control to the host and outside any configured timeout limits. This could enable code execution and resource exhaustion attacks against applications relying on vm2 for code isolation.
Technical details
The vulnerability is a protection mechanism bypass (CWE-693) in vm2's async restriction enforcement. While vm2 blocks direct use of Promise.prototype.then when allowAsync is false by replacing it with a handler that throws an error, it fails to validate thenable objects passed to Promise static methods (Promise.resolve, Promise.all, Promise.race, Promise.any, Promise.allSettled). When these methods assimilate attacker-controlled thenables, native Promise resolution triggers PromiseResolveThenableJob, which invokes the attacker's then method asynchronously in a microtask without passing through the patched then handler. This allows sandboxed code to schedule execution that occurs after VM.run() or NodeVM.run() returns, bypassing both the async restriction and the configured execution timeout. No user interaction is required; the vulnerability is reachable through direct API misuse with allowAsync: false. Patched in vm2 version 3.11.8.
Affected products
- patriksimek vm2 before 3.11.8
Timeline
- 2026-08-27: disclosed: GitHub Security Advisory GHSA-f8gf-w286-fmq2 published
- 2026-09-17: advisory: CVE-2026-92959 published on NVD