Advisories for Npm/Vm2 package

2026

vm2 contains a sandbox escape vulnerability

vm2 NodeVM versions before 3.12.1 contain a sandbox escape vulnerability where the DANGEROUS_BUILTINS denylist omits child_process despite blocking other host-spawning modules. Attackers can require child_process and execute arbitrary commands on the host system when NodeVM is configured with builtin:[''] or explicit child_process allowance. This fork hardens NodeVM with a DANGEROUS_BUILTINS denylist that blocks host‑code‑reaching core modules even when the sandbox requests builtin:[''] or names them explicitly — the list contains …

vm2: util.getCallSites() bypasses GHSA-v27g-jcqj-v8rw host-frame redaction, leaks host call stack

NodeVM exposes the host util module to the sandbox through an unfiltered shallow copy (Object.assign({}, util)). On Node.js >= 22.9 this hands sandboxed code util.getCallSites(), a programmatic stack-introspection API that returns the host process's full call stack — absolute file paths, function names, and line numbers — including vm2 bridge internals and the embedding application's entrypoint. This bypasses the host-frame redaction established in GHSA-v27g-jcqj-v8rw, which only covers the Error.prepareStackTrace channel.

vm2: timeout Option Bypass via FinalizationRegistry Cleanup Callback (Unbounded Host Event-Loop Block)

vm2's VM({ timeout }) option is documented and relied upon as the mechanism that bounds how long sandboxed code may execute. In the current implementation, the timeout only wraps the single synchronous call to VM#run() (via doWithTimeout → this._runScript(script) in lib/vm.js). It does not, and structurally cannot, bound code that the V8 engine itself schedules to run after that call has already returned. FinalizationRegistry and WeakRef are exposed to sandboxed …

vm2: Sandbox Escape (NodeVM)

It being possible to obtain the host proto getter/setter, has been used in many reports: https://github.com/patriksimek/vm2/security/advisories/GHSA-vwrp-x96c-mhwq https://github.com/patriksimek/vm2/security/advisories/GHSA-v6mx-mf47-r5wg https://github.com/patriksimek/vm2/security/advisories/GHSA-grj5-jjm8-h35p https://github.com/patriksimek/vm2/security/advisories/GHSA-47x8-96vw-5wg6 Yet it was never patched… This can, still, be used to escape the sandbox, one example (I'm sure there's other ways as well), is via console._stdout/console._stderr (NodeVM with console: 'inherit', which is the default)

vm2: NodeVM zlib Buffers expose pooled host memory across the VM boundary

When an application explicitly exposes Node's zlib module through vm2's NodeVM builtin allowlist, an untrusted guest can obtain a pool-backed host Buffer from zlib.deflateSync, create a full-width view of its backing ArrayBuffer, read bytes outside the compressed result, and flip a byte in an unrelated host buffer. The pinned vm2 revision reproduces disclosure and host-memory modification, while a sandbox-local Buffer control remains exact-size and non-mutating.

vm2: NodeVM custom resolution bypasses external path boundaries

At source revision 91034466bfb7f56b95fd48083ec6ca36d058f164 of vm2 3.11.8, an untrusted NodeVM guest can turn one allowlisted custom-resolved module into authorization for a separate file whose path merely shares the resolved path's string prefix. LegacyResolver.customResolve stores the resolved path in this.externals as ^<path> without an end or separator boundary; a later absolute require of a sibling such as foo2/index.js therefore passes the external check and is loaded through hostRequire when the configured …

vm2: NodeVM `require.external` without an explicit `require.root` grants unrestricted host filesystem access and full RCE

NodeVM's require.external option lets sandboxed code require() local files and npm packages. When require.external is enabled and require.root is not explicitly set to a path that excludes node_modules, two defaults combine to fully defeat the sandbox: require.root defaults to unrestricted — "if omitted every path is allowed." require.context defaults to "host" — files loaded this way run through the real Node.js require(), not inside any vm2 sandbox. Sandboxed code can …

vm2: Host-returned Promise rejection can bypass vm2's unhandled-rejection hardening and terminate the host process

vm2 current head (v3.11.5, commit 7a1f5100b96f48d34e0fe104ab37c0acc5944f92) can still be used to terminate the host Node.js process when sandbox code calls a host-realm function that returns a rejected host Promise and then ignores the returned value. This is an incomplete-fix variant of the GHSA-hw58-p9xv-2mjh unhandled rejection hardening. The localPromise constructor now catches and consumes sandbox-created unhandled rejections, but host Promises returned across the bridge are not marked handled at the bridge …

vm2: Default VM can mutate host TypedArray and ArrayBuffer intrinsics after the host-prototype pollution fix

vm2's current host-intrinsic prototype protection is incomplete. The fix for GHSA-vwrp-x96c-mhwq blocks sandbox writes into classic host intrinsics such as Object.prototype, Array.prototype, and Function.prototype, but current head still lets sandbox code in a default VM reach and mutate host Uint8Array.prototype, %TypedArray%.prototype, and ArrayBuffer.prototype. After VM.run() returns, normal host typed-array and ArrayBuffer objects observe attacker-controlled properties and methods installed by the sandbox.

vm2: `allowAsync: false` can be bypassed through Promise thenable assimilation in VM and NodeVM

When allowAsync is set to false, vm2 is expected to reject attempts to run asynchronous code. Direct use of Promise.prototype.then is blocked, but Promise static methods still assimilate attacker-controlled thenables. Promise.resolve(thenable), Promise.all([thenable]), Promise.race([thenable]), Promise.any([thenable]), and Promise.allSettled([thenable]) can invoke the thenable's then method in a microtask after VM.run() or NodeVM.run() has already returned. This bypasses the documented async-execution restriction and runs outside the configured timeout, allowing sandboxed code to continue executing …

vm2 sandbox escape via WebAssembly.compileStreaming Promise species bypass

There is a sandbox escape in vm2 3.11.5 / current HEAD when it is used on Node.js 26. The issue is reachable from a default new VM() sandbox. No NodeVM, require permission, host object injection, or intentionally unsafe configuration is required. The escape is a patch-bypass of the same security invariant addressed by GHSA-6j2x-vhqr-qr7q. The earlier fix removed the JSPI entry points WebAssembly.promising and WebAssembly.Suspending, because those APIs exposed a …

vm2 sandbox escape to host RCE via revisited host-wrapped AggregateError bypassing Error sanitization cycle short-circuit

vm2 3.11.6 (this fork's latest release) contains an incomplete-fix bypass of the Error.cause host-reference sanitization added in GHSA-m283-3h24-438v (commit 7e3faaf). Sandbox code that catches a host-wrapped AggregateError which is revisited within a single handleException traversal (self-cycle, mutual-cycle, or the same host aggregate referenced twice in errors[]) receives a live, unsanitized host proxy inside the "sanitized" errors[], yielding full host RCE on the throw channel that the fix and Defense Invariant …

vm2: vm.freeze()/vm.readonly() bypass via accessor descriptor

Untrusted JavaScript running inside new VM().run() / new NodeVM().run() can bypass vm.freeze() / vm.readonly() and mutate a host object the embedder explicitly marked read-only - the documented contract is "prevent sandboxed scripts from adding, changing, or deleting properties". If the frozen host object has an accessor (get/set) own-property, the sandbox can read the host setter back out via Object.getOwnPropertyDescriptor() and call it directly; the call lands in BaseHandler.apply which unwraps …

vm2: NodeVM node:-prefixed negative builtin deny bypass exposes child_process

NodeVM normalizes node:-prefixed builtin specifiers during require() resolution, but it does not normalize user-provided negative builtin entries in wildcard policy. As a result, this configuration: new NodeVM({ require: { builtin: ['*', '-node:child_process'] } }); does not deny the canonical child_process builtin. Sandboxed code can require both child_process and node:child_process, and receives the host module with process-spawning APIs such as execSync and spawn. The safe proof below only checks module and …

vm2: NodeVM nesting guard accepts array-shaped require and permits host RCE

The NodeVM constructor computes hasRealRequireConfig using typeof requireOpts === 'object' && requireOpts !== null, so require: [] bypasses the guard intended to reject nesting without an explicit require configuration. makeResolverFromLegacyOptions() then destructures the array to undefined option fields and returns a resolver containing only NESTING_OVERRIDE.vm2. Any attacker whose JavaScript is executed by a downstream NodeVM configured with {nesting: true, require: []} can load the host vm2 module, create an inner …

vm2: NodeVM builtin denylist bypass via fs/promises despite -fs, allowing host filesystem writes

NodeVM's builtin wildcard policy can allow sandboxed code to access fs/promises even when the embedder denies fs. With the following configuration: require: { builtin: ['*', '-fs', '-child_process'] } require('fs') and require('child_process') are blocked, but require('fs/promises') and require('node:fs/promises') are still available. This allows sandboxed code to create and write files on the host filesystem through the promise-based filesystem API.

vm2: NodeVM builtin allowlist bypass via node:test.run() execArgv allows sandbox escape

On Node.js 24 and newer, vm2 can expose the host node:test module to sandboxed NodeVM code when the embedder explicitly allows the node:test builtin. Sandbox code can reach that module through require('node:node:test') and call run() with attacker-controlled execArgv. node:test.run() starts a separate Node process for process-isolated test execution and forwards the supplied execArgv values to that process. Supplying –eval=<JavaScript> therefore executes arbitrary JavaScript in an unrestricted host Node process, outside …

vm2: Incomplete nodejs.* symbol filtering lets sandbox override host WebStream state checks

vm2 current head (v3.11.5, commit 7a1f5100b96f48d34e0fe104ab37c0acc5944f92) still exposes registered Node.js internal symbols from host WebStream prototypes to sandbox code. The prior nodejs.* symbol hardening blocks Symbol.for('nodejs.<name>') at the source, but the extraction filters and bridge write traps still enumerate a fixed set of known registered symbols. On Node.js v25.8.0, stream/web exposes two additional registered symbols: nodejs.stream.disturbed nodejs.stream.errored Sandbox code can extract those real host symbols with Object.getOwnPropertySymbols(streamWeb.ReadableStream.prototype) and then use …

vm2: GHSA-m283-3h24-438v fix bypass leads to host RCE via call/apply indirection

Untrusted JavaScript run by vm2 can escape the sandbox and execute arbitrary commands in the host Node.js process when an embedder-exposed host Promise rejects. This is an incomplete fix for GHSA-m283-3h24-438v: the advisory's capability-bearing rejection rebuild runs only through this direct Promise-handler path, so call/apply indirection bypasses the protection it introduced. The bridge sanitises host rejection values before sandbox callbacks run, but the gate at lib/bridge.js:1624 identity-checks only the direct …

vm2: External module allowlist uses a raw prefix test, so a prefix-sharing sibling package is treated as allowlisted

isPathAllowedForModule decides whether a resolved path belongs to an allowlisted external module using a raw string prefix test. node_modules/foo2 starts with node_modules/foo, so a package whose name merely shares a prefix with an allowlisted one is treated as being inside it, and a relative require from the allowlisted package reaches it even with transitive loading disabled.

vm2 sandbox escape on Node.js 26 through a stale PromiseThenLookupChain protector

The latest published vm2 release, 3.11.5, and the current main branch are vulnerable to a sandbox escape when used on Node.js 26. An ordinary fulfilled Promise created by an async function can retain an attacker-controlled constructor[Symbol.species] across Promise.prototype.finally(). vm2 installs wrappers on the intrinsic Promise.prototype.then and catch methods. On Node.js 26 / V8 14.6, V8's SetPrototypeProperties path updates these existing data properties without invalidating the PromiseThenLookupChain protector. Promise.prototype.finally() subsequently trusts …

vm2 NodeVM can replace the host process TLS trust store

Summary vm2 3.11.6 exposes the host tls module to a NodeVM when that builtin is explicitly allowed. Although the module object is wrapped as read-only, its functions still execute against process-wide host state. On Node.js versions that provide tls.setDefaultCACertificates(), sandbox code can replace the certificate authorities trusted by subsequent host-realm TLS clients. The exploit needs only the narrowly allowed tls and url builtins. It does not require fs, process, module, …

vm2 exposes host HTTPS credentials and TLS traffic through globalAgent

Summary vm2 3.11.6 exposes the host process's real https.globalAgent when a NodeVM is explicitly allowed to require https. The module is wrapped as read-only, but calls to methods on the shared agent still mutate the host object. Sandbox code can register a free listener and receive host request options and the host TLS socket whenever an unrelated host HTTPS request releases a pooled connection. In a contained test, sandbox code …

vm2 Custom Module Resolver Can Bypass the External Package Allowlist by Loading a Colliding Host Package

vm2 is a sandbox library for isolating and executing untrusted JavaScript code inside a Node.js process. It can restrict access to built-in modules and external packages. When NodeVM enables an external allowlist together with a custom resolve callback, vm2 checks the requested package name with a non-exact match. For example, if the allowlist only permits left-pad, an attacker can still bypass the check with a colliding package name such as …

vm2 crypto builtin loads attacker native code through setEngine

Summary vm2 3.11.6 exposes the host crypto module to a NodeVM when that single builtin is allowed. The module is presented through a read-only bridge, but its functions still execute with host-process authority. crypto.setEngine() accepts a filesystem path and asks OpenSSL to dynamically load the referenced native library. An attacker whose untrusted plugin package contains a native library can therefore load that library into the host process by calling crypto.setEngine() …

vm2 CLI provides no sandbox isolation - host-realm require() is reachable from sandboxed scripts

The vm2 command-line tool installed by npm install -g vm2 and documented in the README's "CLI" section runs the supplied script under NodeVM with require:{external:true} and no root / context / builtin configured. With these defaults the resolver loads every relative or absolute require() target through the host require() function, executing the attacker's module body in the host Node.js process before the result is ever proxied back into the sandbox. …

vm2 allows a sandboxed plugin to execute native code through `node:sqlite`

vm2 3.11.6 exposes Node.js's host node:sqlite module to NodeVM code when that builtin is allowed explicitly or through builtin: ['*']. The module is wrapped as read-only, but callable methods retain host-process authority. A sandboxed plugin can construct an in-memory database with extension loading enabled and call DatabaseSync.loadExtension() on a native library bundled in the plugin directory. SQLite loads the library into the Node.js host process and invokes its native extension …

vm2's bufferAllocLimit cap bypassed by Buffer.concat and Buffer.from arrayLike

vm2 bufferAllocLimit cap bypassed by Buffer.concat and Buffer.from arrayLike The bufferAllocLimit option introduced in 3.11.0 (GHSA-6785-pvv7-mvg7) caps host-side Buffer allocations driven by sandbox code, the way embedders opt into timeout. The cap wraps Buffer.alloc, Buffer.allocUnsafe, Buffer.allocUnsafeSlow, and the deprecated Buffer(N) / new Buffer(N) forms. Two other API paths reach the same host C++ allocator with an attacker-controlled size and are not capped: Buffer.concat(list, totalLength) and Buffer.from(arrayLike) with a fake length. …

vm2: NodeVM `builtin: ['*']` exposes `os` and `dns` — process-wide observability reads AND writes that hijack the host (sibling class of GHSA-9g8x-92q2-p28f)

GHSA-9g8x-92q2-p28f closed the "process-wide observability builtins" class by adding diagnostics_channel, async_hooks, perf_hooks, and v8 to DANGEROUS_BUILTINS in lib/builtin.js. The fix's rationale (in the commit message and docs/ATTACKS.md Category 35) is general: Process-wide observability builtins. Unlike most Node builtins, these expose state of the entire host process rather than sandbox-local state — the vm2 boundary cannot usefully contain them because the data they surface […] belongs to the embedder. Even a …

VM2 has Missing Error.cause Sanitization that Enables Sandbox Escape to RCE

I found that handleException() in lib/setup-sandbox.js recursively sanitizes sub-errors for SuppressedError and AggregateError, but completely ignores the ES2022 Error.cause property. When sandbox code catches a host-thrown error carrying a .cause that references a host object like process, it can traverse that reference to achieve arbitrary command execution on the host. The project's own docs/ATTACKS.md (Defense Invariant #3, line 54) explicitly claims Error.cause is sanitized. The implementation does not match this …

vm2's Bridge Proxy set trap ignores receiver parameter, enabling host object property injection via prototype chain

The BaseHandler.set trap in bridge.js (line 1231) ignores the receiver parameter and unconditionally writes to the host target object. Per the Proxy set trap specification, when receiver !== proxy (e.g., when a child object inherits from the proxy via Object.create), the property assignment should create an own property on the receiver, not on the proxy target. The current implementation always calls otherReflectSet(object, key, value) against the host target, causing all …

vm2 setup-sandbox.js violates Defense Invariant #11 in stack-trace formatter

defaultSandboxPrepareStackTrace in lib/setup-sandbox.js (lines 605, 607) appends to a fresh sandbox-realm lines = [] via lines[lines.length] = value. This is the exact invariant-violating pattern that GHSA-9qj6-qjgg-37qq (commit ca195f0, 2026-05-01) just patched in neutralizeArraySpeciesBatch and codified as Defense Invariant #11 ("Bridge-internal containers must not invoke sandbox code"). A sandbox-installed Array.prototype[N] setter fires during the bridge's safe-default stack-trace formatting and observes / intercepts each appended line.

vm2 sandbox escape via JSPI-backed Promise `.finally()` species bypass

A sandbox escape vulnerability in vm2 allows arbitrary code execution in the host process when untrusted code is executed with async support on runtimes exposing WebAssembly JSPI (WebAssembly.promising / WebAssembly.Suspending). In the tested configuration, a JSPI-backed Promise can reach Promise.prototype.finally() in a way that bypasses the expected Promise-species hardening and exposes a host-originated rejection object to attacker-controlled species logic, breaking the sandbox boundary. This is a critical sandbox escape: any …

vm2 has a sandbox escape via unblocked cross-realm Symbol.for keys + missing bridge write-trap symbol checks

vm2 3.11.2 Symbol.for override in setup-sandbox.js only intercepts 2 of 9 dangerous Node.js cross-realm symbols. Combined with the bridge's set/defineProperty/deleteProperty traps having no isDangerousCrossRealmSymbol key check, sandbox code can obtain real cross-realm symbols, write them to host objects, and control host-side behavior — verified with a full util.promisify hijack chain.

vm2 has a Sandbox Escape issue

By combining Buffer.call.call({}.lookupGetter, Buffer, "proto"), Buffer.call.call({}.lookupSetter, Buffer, "proto"), and Node.js's ERR_INVALID_ARG_TYPE Error, the host's TypeError constructor can be obtained, which allows the escape from the sandbox. This allows attackers to run arbitrary code.

vm2 has a CVE-2023-37903 patch bypass: nesting:true without explicit require still allows full RCE

The fix for GHSA-8hg8-63c5-gwmx (CVE-2023-37903) introduced a check in nodevm.js line 263 that blocks the combination nesting: true + require: false. However, the check uses strict equality (options.require === false), which is trivially bypassed by omitting the require option entirely. When require is not specified, options.require is undefined, not false. The strict equality check fails, so the security guard is skipped. Immediately after (line 280), the destructuring default require: requireOpts …

NodeVM observability builtins leak host process and HTTP request data

NodeVM exposes some process-wide observability builtins when they are allowed through require.builtin. The following builtins are not blocked by the dangerous builtin denylist: diagnostics_channel async_hooks perf_hooks These modules are process-wide, not sandbox-local. Sandboxed code can use them to observe host application data across the vm2 boundary. Note: It is a host data exposure issue. The impact depends on whether the host application allows these builtins and uses HTTP, async request …

NodeVM network builtin exclusions bypass via internal _http_client and _http_server

NodeVM supports excluding public network builtins from the wildcard builtin option. With this configuration direct access to http, https, http2, net, dgram, tls, dns, and dns/promises is blocked. However, Node.js also exposes underscored internal HTTP builtins such as _http_client and _http_server. These are not blocked when the public modules are excluded. Sandboxed code can use these internal builtins to make outbound HTTP requests and open listening HTTP sockets even though …

vm2's Transformer Fast-Path Bypass Exposes Internal State Variable

vm2's code transformer has a performance optimization that skips AST analysis when the code does not contain catch, import, or async keywords. This fast-path bypass allows sandboxed code to directly access the internal VM2_INTERNAL_STATE_DO_NOT_USE_OR_PROGRAM_WILL_FAIL variable, which exposes internal security functions (handleException, wrapWith, import).

vm2: Mutable Proxies for Host Intrinsic Prototypes Allows Sandbox Escape

vm2's bridge exposes mutable proxies for real host-realm intrinsic prototypes and then forwards sandbox writes into the underlying host objects with otherReflectSet() and otherReflectDefineProperty(), which lets attacker-controlled JavaScript running in a default VM or inherited NodeVM mutate shared host Object.prototype, Array.prototype, and Function.prototype from inside the sandbox.

vm2 NodeVM `nesting: true` bypasses `require: false` allowing sandbox escape and arbitrary OS command execution

When a NodeVM is created with nesting: true, sandbox code can unconditionally require('vm2') regardless of the outer VM's require configuration — including require: false. With access to vm2, the sandbox constructs a new inner NodeVM with its own unrestricted require settings and executes arbitrary OS commands on the host. Any application that runs untrusted code inside a NodeVM with nesting: true is fully compromised.

vm2 Host Promise Resolution Preserves Object Identity Across Sandbox Boundary

A sandbox boundary violation in vm2 allows host object identity to cross into the sandbox through host Promise resolution. When a host-side Promise that resolves to a host object is exposed to the sandbox, the value delivered to the sandbox .then() callback preserves host identity. This allows the sandbox to interact with the host object directly, including: Performing identity checks using host-side WeakMap Mutating host object state from inside the …

vm2 has a NodeVM require.root bypass via symlink traversal that allows sandbox escape

NodeVM's require.root path restriction can be bypassed using filesystem symlinks, allowing sandboxed code to load modules from outside the allowed root directory in host context. Because path validation uses path.resolve() (which does not dereference symlinks) but module loading uses Node's native require() (which does), an attacker can load arbitrary host-realm modules and achieve remote code execution.

vm2 has a NodeVM builtin allowlist bypass via `module` builtin's `Module._load` that allows sandbox escape

NodeVM's builtin allowlist can be bypassed when the module builtin is allowed (including via the '*' wildcard). The module builtin exposes Node's Module._load(), which loads any module by name directly in the host context, completely bypassing vm2's builtin restriction. This allows sandboxed code to load excluded builtins like child_process and achieve remote code execution.

vm2 has a Sandbox Escape

In vm2 for version 3.10.0, Promise.prototype.then Promise.prototype.catch callback sanitization can be bypassed. This allows attackers to escape the sandbox and run arbitrary code. const { VM } = require("vm2"); const code = ` const error = new Error(); error.name = Symbol(); const f = async () => error.stack; const promise = f(); promise.catch(e => { const Error = e.constructor; const Function = Error.constructor; const f = new Function( "process.mainModule.require('child_process').execSync('echo HELLO …

2023

Improper Neutralization of Special Elements in Output Used by a Downstream Component ('Injection')

vm2 is a sandbox that can run untrusted code with Node's built-in modules. In versions 3.9.17 and lower of vm2 it was possible to get a read-write reference to the node inspect method and edit options for console.log. As a result a threat actor can edit options for the console.log command. This vulnerability was patched in the release of version 3.9.18 of vm2. Users are advised to upgrade. Users unable …

Improper Neutralization of Special Elements in Output Used by a Downstream Component ('Injection')

vm2 is a sandbox that can run untrusted code with Node's built-in modules. A sandbox escape vulnerability exists in vm2 for versions up to and including 3.9.17. It abuses an unexpected creation of a host object based on the specification of Proxy. As a result a threat actor can bypass the sandbox protections to gain remote code execution rights on the host running the sandbox. This vulnerability was patched in …

Improper Neutralization of Special Elements in Output Used by a Downstream Component ('Injection')

vm2 is a sandbox that can run untrusted code with allow listed Node's built-in modules. There exists a vulnerability in exception sanitization of vm2 for versions up to 3.9.16, allowing attackers to raise an unsanitized host exception inside handleException() which can be used to escape the sandbox and run arbitrary code in host context. This vulnerability was patched in the release of version 3.9.17 of vm2. There are no known …

Improper Control of Dynamically-Managed Code Resources

vm2 is a sandbox that can run untrusted code with allow listed Node's built-in modules. Prior to version 3.9.15, vm2 was not properly handling host objects passed to Error.prepareStackTrace in case of unhandled async errors. A threat actor could bypass the sandbox protections to gain remote code execution rights on the host running the sandbox. This vulnerability was patched in the release of version 3.9.15 of vm2. There are no …

2022

Improper Control of Dynamically-Managed Code Resources

vm2 is a sandbox that can run untrusted code with allow listed Node's built-in modules. In versions prior to version 3.9.11, a threat actor can bypass the sandbox protections to gain remote code execution rights on the host running the sandbox. This vulnerability was patched in the release of version 3.9.11 of vm2. There are no known workarounds.

Uncontrolled Recursion

This affects the package vm2 before 3.6.11. It is possible to trigger a RangeError exception from the host rather than the "sandboxed" context by reaching the stack call limit with an infinite recursion. The returned object is then used to reference the mainModule property of the host code running the script allowing it to spawn a child_process and execute arbitrary code.

2021