A nullish this receiver bug in vm2's bridge lets sandboxed script reach the host realm's global object and execute arbitrary code on the host.
What Is It
vm2 does not correctly handle a nullish this receiver in the apply trap of its bridge (lib/bridge.js). When sandboxed code calls a host-provided non-strict (sloppy-mode) function without a receiver, for example fn(), a detached method, fn.call(), fn.apply(undefined), Reflect.apply(fn, undefined, []), or fn.bind()(), the undefined receiver is passed straight through to the host call. V8 then substitutes the host realm's global object for this, and vm2 wraps and returns that object back into the sandbox, handing untrusted script a live proxy of the host global.
The result is a complete sandbox escape. Untrusted script can reach process and execute arbitrary code or commands on the host, for example via process.getBuiltinModule('child_process').execSync. The flaw is classified as CWE-94 (code injection).
Why It Matters
vm2 is used to isolate untrusted JavaScript. A full escape collapses that trust boundary entirely, turning any user-supplied script into host command execution; remotely, without authentication or user interaction, wherever an application accepts untrusted script for sandboxed evaluation.
The impact is not limited to the sandbox process itself: once script holds a reference to the host global, confidentiality, integrity, and availability of the embedding application and anything reachable from it are all in scope.
No severity score or active-exploitation status is asserted here; neither is established by the advisories cited below. Check NVD and the CISA KEV catalog directly before using scoring or exploitation status in prioritization decisions.
What's Vulnerable
- Vendor: patriksimek; Product:
vm2(pkg:npm/vm2)
The cited VulnCheck advisory describes the affected range as "vm2 before 3.12.1," with 3.12.1 and later fixed. Treat those version identifiers as unverified: the published version list on the vm2 npm package page (cited below) tops out in the 3.9.x line, with no 3.12.0 or 3.12.1 release corresponding to the advisory's range. Confirm the affected and fixed versions against the upstream GitHub Security Advisory and the package's release list before scoping your own exposure.
Exploitation requires that the embedding application expose at least one non-strict host function to the sandbox. Strict-mode and ES module host functions are not affected.
Patch Status
Upgrade to the fixed release identified by the upstream advisory, after confirming that version exists in the published release history. Note that the vm2 npm package page (cited below) carries a maintainer deprecation notice, so migrating off it, to an isolate-based sandbox such as isolated-vm, or to an out-of-process boundary, is the durable remediation rather than a version bump.
Where an immediate upgrade is not possible, the exposure depends on handing non-strict host functions to the sandbox. Audit what the sandbox is given and convert exposed host functions to strict mode or ES modules, which are unaffected by this receiver-substitution behavior.
Sources
- vm2 GitHub Security Advisory GHSA-j89j-5m6r-cr2q; https://github.com/patriksimek/vm2/security/advisories/GHSA-j89j-5m6r-cr2q
- VulnCheck Advisory: vm2 before 3.12.1 sandbox escape RCE via non-strict host function; https://www.vulncheck.com/advisories/vm2-before-3.12.1-sandbox-escape-rce-via-non-strict-host-function
- npm package page for
vm2(deprecation notice and published version list), https://www.npmjs.com/package/vm2