Unpatched vm2 Sandbox Escape on Node.js 26: Stale V8 Promise Protector Bypasses finally() Hardening
What happened
A researcher (handle YMsora) disclosed a sandbox escape in vm2 3.11.5 (the latest published release) and the current GitHub main branch, affecting any default new VM() configuration when run on Node.js 26.0.0 through 26.7.0 (V8 14.6). According to the report, vm2 installs wrappers over the intrinsic Promise.prototype.then/catch to enforce its sandbox hardening, but on V8 14.6 the engine's SetPrototypeProperties optimization updates those properties without invalidating the PromiseThenLookupChain protector. Promise.prototype.finally() then trusts the stale protector and calls the native then directly via an internal fast path, skipping vm2's wrapper and its resetPromiseSpecies reset entirely.
The report states this lets an attacker-controlled Symbol.species constructor supply the resolve/reject functions for a native Promise reaction. By triggering a calibrated stack overflow at that reaction boundary, a host-realm RangeError is handed to the attacker's reject function, and its constructor chain reaches the host Function constructor and process object. The PoC described is non-destructive (reads only process.version), and reproduction was reported across Linux/glibc, Linux/musl, and Windows x64 — not platform-specific. The report also notes the underlying V8 protector bug is already public and fixed upstream in V8, but no vm2 fix exists yet. CVE-2026-92944 has been assigned, with a reported CVSS of 9.8 and public PoC availability.
Why it matters for defenders
vm2 is widely used to execute untrusted or third-party JavaScript inside Node.js applications (plugin systems, code-execution services, CI tooling, etc.). Per the report, the escape works with the default new VM() configuration — no WebAssembly, no eval, no exposed host objects, and no custom embedder Promise are required. If accurate, this means any application pairing vm2 with Node.js 26.x is exposed by default, and the vulnerability sits exactly at the trust boundary vm2 exists to enforce: successful exploitation reportedly yields arbitrary code execution with the host process's privileges, including filesystem, credential, network, and child-process access. The report also distinguishes this from three prior vm2/Promise CVEs (CVE-2026-22709, CVE-2026-47208, CVE-2026-47210), noting this path is distinct and reportedly still works against the versions that fixed those earlier issues.
What defenders should watch for or do now
- Inventory where vm2 is used to sandbox untrusted JavaScript, and check which Node.js major version those services run — per the report, exposure is specific to Node.js 26.0.0–26.7.0 (V8 14.6.202.x); Node 22/24/25 reportedly tested safe.
- Until a vm2 fix ships, the report suggests the upstream V8 protector fix could be backported, or Node could be pinned to an unaffected version/line for any process running vm2.
- The report identifies
node --no-proto-assign-seq-optas a verified control that changed results from exploit success to safe in testing — treat this as a stopgap mitigation to evaluate, not a permanent fix, and validate independently before relying on it. - From a hunting perspective, consider monitoring vm2-sandboxed processes for anomalous child-process spawning, unexpected filesystem/network activity, or crash/restart patterns consistent with repeated stack-depth probing, since the described exploit path involves deliberately triggering stack overflows at a calibrated depth.
- Treat vm2 itself with caution for new designs — the report frames this as the fourth distinct Promise-related escape disclosed against it, which may inform longer-term decisions about sandboxing technology choice.
Developing situation
This is based on a single advisory disclosure published today, with no vendor-shipped fix confirmed at the time of writing; details here reflect what has been reported and may be revised as vm2 maintainers and the community respond. Review the full GitHub Security Advisory for technical specifics, reproduction steps, and updates: GHSA-27g9-p43v-cw3v.