CVE-2026-92942: vm2 before 3.11.7 Timeout Bypass via FinalizationRegistry
vm2 before 3.11.7 (affected versions <= 3.11.6) does not enforce the VM({ timeout }) option on code executed outside the synchronous VM#run() call. The timeout only wraps the single call to runScript() via doWithTimeout() in lib/vm.js, and FinalizationRegistry and WeakRef are exposed to sandboxed code unmodified (they are not among the hardened globals in lib/setup-sandbox.js). Sandboxed code can register a FinalizationRegistry cleanup callback against an object and then drop the only strong reference to it; vm.run() returns within the configured timeout, but when the V8 garbage collector later reclaims the object it invokes the sandboxed cleanup callback outside any vm2 timeout accounting. A busy loop in that callback blocks the host event loop for an unbounded period, resulting in denial of service. The time of invocation depends on the garbage collector (e.g. under memory pressure or with --expose-gc).
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
vm2to a version that resolves this vulnerability.Fixed in 3.11.7 - Compensating control
Mitigate the timeout-bypass denial of service by not running untrusted code that can use FinalizationRegistry/WeakRef for cleanup callbacks outside vm2’s synchronous VM#run() timeout accounting.
Event History
Frequently Asked Questions
Which deployments are exposed to denial of service?
Deployments using npm/vm2 version 3.11.6 or earlier are affected when sandboxed code can use FinalizationRegistry or WeakRef. The impact is a host event-loop block caused by code running after VM#run() has returned.
What does an attacker need to exploit this?
An attacker needs the ability to execute JavaScript in the vm2 sandbox. They can register a FinalizationRegistry cleanup callback, release the registered object, and place a busy loop in the callback; garbage collection later invokes it outside the configured timeout.
How can I determine whether timeout protections can be bypassed in my environment?
Check whether your application uses vm2 3.11.6 or earlier and relies on VM({ timeout }) to limit sandbox execution. If sandboxed code can access the default exposed FinalizationRegistry and WeakRef globals, the timeout does not cover cleanup callbacks triggered by garbage collection.
What should be done to remediate this issue?
Update vm2 to version 3.11.7 or later. Until updating, do not rely on VM({ timeout }) as a complete execution limit for sandbox code that can use FinalizationRegistry or WeakRef.