Skip to content

chore(deps): bump vm2 from 3.9.19 to 3.11.5#1298

Merged
Spiral-Memory merged 1 commit into
developfrom
dependabot/npm_and_yarn/vm2-3.11.5
May 18, 2026
Merged

chore(deps): bump vm2 from 3.9.19 to 3.11.5#1298
Spiral-Memory merged 1 commit into
developfrom
dependabot/npm_and_yarn/vm2-3.11.5

Conversation

@dependabot
Copy link
Copy Markdown
Contributor

@dependabot dependabot Bot commented on behalf of github May 18, 2026

Bumps vm2 from 3.9.19 to 3.11.5.

Release notes

Sourced from vm2's releases.

v3.11.5

What's Changed

Bug fixes

  • #566 — Restore util.inspect output on Node 26+. console.log(vm.run(...)) was rendering as Proxy(Proxy({})) / Proxy(Proxy([])) instead of the underlying value. Triggered by Node 26's stricter handling of nested proxies in the inspector.
  • #567 — Restore array iteration on vm.freeze()'d host arrays. Calling .map() / .filter() / .forEach() etc. inside the sandbox on a frozen host object containing arrays threw TypeError: 'isExtensible' on proxy: trap result does not reflect extensibility of proxy target. Regression from the 3.11.0 proxy-invariant hardening.
  • #568 — Fix .node extension handler key in lib/resolver.js (the key was ' .node' with a leading space, so native addon resolution silently fell through to the default path). Thanks to @​cherr-cc.

Upgrade Notes

Drop-in replacement for 3.11.4. No API or configuration changes.

Full Changelog: patriksimek/vm2@v3.11.4...v3.11.5

v3.11.4

Ten advisories closed. Patch release — no API changes for valid configurations.

What's Changed

Security fixes

  • GHSA-c4cf-2hgv-2qv6 — Bridge set trap ignoring ECMA-262 §9.5.9 Receiver, letting Object.create(hostObj) children and Reflect.set(hostObj, k, v, custom) writes leak onto the host object (write-channel → RCE).
  • GHSA-m5q2-4fm3-vfqp — Cross-realm Symbol.for namespace leak + missing dangerous-symbol guards on the bridge's write traps (set / defineProperty / deleteProperty), enabling sandbox-installed nodejs.util.promisify.custom / stream brand / webstream hooks on host objects (RCE).
  • GHSA-v6mx-mf47-r5wg — Host prototype mutation via Function.prototype.{call,apply,bind} and Reflect.{apply,construct} indirection through Object.prototype.__proto__ setter, severing host intrinsic prototype chains and escaping via thisEnsureThis proto-walk fallthrough (RCE).
  • GHSA-q3fm-4wcw-g57x — Defense Invariant #11 violation in defaultSandboxPrepareStackTrace (second variant of GHSA-9qj6-qjgg-37qq in a different file): sandbox-installed Array.prototype[N] setter / Array.prototype.join override could observe bridge-internal stack-trace state.
  • GHSA-76w7-j9cq-rx2j — Promise species hijack in localPromise's swallow-tail, hijacking the downstream child constructor to capture V8's internal (resolve, reject) capability and reach a raw host-realm error → host Function (RCE).
  • GHSA-m4wx-m65x-ghrr — NodeVM constructor patch bypass of GHSA-8hg8-63c5-gwmx: any truthy nesting paired with a non-real-config require produced a NESTING_OVERRIDE-only resolver → inner NodeVM with attacker-chosen requirechild_process RCE.
  • GHSA-6j2x-vhqr-qr7q — WebAssembly JSPI (WebAssembly.promising / WebAssembly.Suspending, Node 24+ behind a flag, Node 26+ default) producing Promise objects with a host-realm [[Prototype]] chain and no bridge interposition; species hijack delivers a raw host-realm rejection to sandbox .catch → host Function (RCE).
  • GHSA-rp36-8xq3-r6c4 — NodeVM builtin denylist bypass via process (whose getBuiltinModule(name) reloads any core module regardless of allow/deny config) and inspector/promises (whose Session().post('Runtime.evaluate', ...) evaluates attacker JS in the host realm). Supersedes GHSA-947f-4v7f-x2v8.
  • GHSA-r9pm-gxmw-wv6p — NodeVM builtin: ['*'] wildcard exposing Node's undocumented underscored network builtins (_http_client, _http_server, _tls_*, _stream_*) even when the documented -http/-https/-net/-tls exclusions were used — SSRF-class capability bypass (CVSS 8.6).
  • GHSA-9g8x-92q2-p28f — NodeVM builtin allowlist surfacing four process-wide observability builtins (diagnostics_channel, async_hooks, perf_hooks, v8) that read state of the entire host process rather than sandbox-local state — HTTP header / async-context / perf-mark / heap-snapshot exfiltration.

Documentation

  • docs/ATTACKS.md extended through Category 35, plus two new Defense Invariants: #12 ("No sandbox-visible object has a host-realm prototype chain without bridge interposition") and #13 ("The NodeVM builtin allowlist is a closed system").

Upgrade Notes

  • If you constructed NodeVM({ nesting: <truthy> }) without an explicit require config object, new NodeVM(...) now throws (GHSA-m4wx-m65x-ghrr). This covers every shape that previously silently produced a vm2-only resolver: omitting require, or setting it to any falsy value (false/undefined/null/0/'') or any truthy non-object value (true/number/string/symbol/function); and also any truthy nesting value, not only nesting: true. Either drop nesting, or pass an explicit require config object (e.g. require: { builtin: [] }) to acknowledge that vm2 will be requireable from inside the sandbox. The error message is actionable and links to the README hardening section.
  • No other valid configurations are affected. Embedders who explicitly listed any of process / inspector / worker_threads / cluster / vm / repl / module / trace_events / wasi / diagnostics_channel / async_hooks / perf_hooks / v8 in builtin were already running an unsandboxed sandbox; those names now throw at load time and can be re-introduced as safe wrappers via mock / override / SPECIAL_MODULES.

Full Changelog: patriksimek/vm2@v3.11.3...v3.11.4

v3.11.3

What's Changed

Security fix

... (truncated)

Changelog

Sourced from vm2's changelog.

[3.11.5]

Patch release — no API changes.

Fix

  • #566util.inspect of vm.run(...) results rendered as Proxy(Proxy({})) on Node 26+. Install nodejs.util.inspect.custom on host-side proxy targets so the inspect output reflects the underlying shape.
  • #567 — Array iteration methods on a vm.freeze()-d host array threw an 'isExtensible' on proxy invariant error (regression from the GHSA-grj5-jjm8-h35p species defense). Align the ReadOnly proxy target's extensibility with its trap result and skip species neutralization on the host→sandbox apply path.

[3.11.4]

Ten advisories closed. Patch release — no API changes for valid configurations.

Security fixes

  • GHSA-c4cf-2hgv-2qv6 — bridge escape via BaseHandler.set ignoring the ECMA-262 §9.5.9 Receiver argument; Object.create(hostProxy).x = v and Reflect.set(hostProxy, k, v, sandboxObj) wrote through to the host object instead of installing on the receiver, turning every embedder-exposed host object into a sandbox write channel. Receiver-gated install-on-receiver fix in lib/bridge.js mirroring ReadOnlyHandler.set. See ATTACKS.md Category 32 and test/ghsa/GHSA-c4cf-2hgv-2qv6/.
  • GHSA-m5q2-4fm3-vfqp — sandbox escape via unblocked cross-realm Symbol.for keys plus missing dangerous-symbol guards on the bridge's write traps. Two-layer structural fix: lib/setup-sandbox.js denies the entire nodejs. namespace at Symbol.for and aligns the read-side filters with the full 9-symbol cache, and lib/bridge.js extends isDangerousCrossRealmSymbol and applies it to the set/defineProperty/deleteProperty traps. See ATTACKS.md Category 8 / Category 20 (both extended) and test/ghsa/GHSA-m5q2-4fm3-vfqp/.
  • GHSA-v6mx-mf47-r5wg — host prototype mutation via apply-trap indirection. Sandbox code could reach host prototype-mutating setters (Object.prototype.__proto__, setPrototypeOf, defineProperty, __defineSetter__/__defineGetter__) through Function.prototype.{call,apply,bind} and Reflect.{apply,construct} indirection, sever a host intrinsic's prototype chain, and escape via the bridge's thisEnsureThis proto-walk fallthrough. Two-layer structural fix in lib/bridge.js (apply-trap blocklist + cache check before proto-walk). See ATTACKS.md Category 30 and test/ghsa/GHSA-v6mx-mf47-r5wg/.
  • GHSA-q3fm-4wcw-g57x — Defense Invariant #11 hardening for defaultSandboxPrepareStackTrace (second variant of GHSA-9qj6-qjgg-37qq in a different file). The sandbox stack-trace formatter accumulated frames in a sandbox-realm array and .join-ed them, so a sandbox-installed setter on Array.prototype[N] (or .join override) observed bridge-internal state — no host reference reachable today, but one enrichment away from regressing into the GHSA-9qj6 RCE shape. Fixed in lib/setup-sandbox.js by folding frames through a primitive string accumulator (no Array.prototype slot reachable) and converting makeCallSiteGetters to localReflectDefineProperty for symmetry. See ATTACKS.md Category 28 Variant B and test/ghsa/GHSA-q3fm-4wcw-g57x/.
  • GHSA-76w7-j9cq-rx2j — Promise species hijack in the localPromise swallow tail. The swallow-tail apply(globalPromisePrototypeThen, this, [...]) call inside localPromise's constructor invoked the cached host Promise.prototype.then without first calling resetPromiseSpecies(this), so a sandbox subclass overriding [Symbol.species] could redirect the downstream child constructor to a user function and capture V8's internal (resolve, reject) capability — delivering a raw host-realm error (RangeError from deep recursion + e.stack) to a sandbox collector and reaching the host Function constructor via .constructor.constructor. One-line fix in lib/setup-sandbox.js adds the missing resetPromiseSpecies(this) before the swallow-tail call, matching the pattern already used by the .then/.catch/Reflect.apply overrides. See ATTACKS.md Category 31 and test/ghsa/GHSA-76w7-j9cq-rx2j/.
  • GHSA-m4wx-m65x-ghrr — NodeVM constructor patch bypass of GHSA-8hg8-63c5-gwmx: a truthy nesting paired with anything other than a real require config object produced a NESTING_OVERRIDE-only resolver → inner NodeVM with attacker-chosen requirechild_process RCE. Structural fix in lib/nodevm.js: destructure first, then reject at construction whenever nesting is truthy and requireOpts is not a non-null object or Resolver. Supersedes GHSA-8hg8-63c5-gwmx. See ATTACKS.md Category 25 and test/ghsa/GHSA-m4wx-m65x-ghrr/.
  • GHSA-6j2x-vhqr-qr7q — sandbox escape via WebAssembly JSPI (Node 24 behind --experimental-wasm-jspi, Node 26+ default). WebAssembly.promising returns Promise objects whose [[Prototype]] chain points directly at the host realm's Promise.prototype with no bridge proxy in between, so p.finally() reaches host Promise.prototype.finally, V8's SpeciesConstructor reads an attacker-controlled p.constructor getter, and the eventual host-realm rejection is dispatched through the attacker's class with no bridge wrapping — e.constructor.constructor('return process')() then evaluates in the host realm. Structural fix in lib/setup-sandbox.js: delete WebAssembly.promising and WebAssembly.Suspending at sandbox bootstrap, mirroring the existing WebAssembly.JSTag removal. Adds Defense Invariant #12 (no sandbox-visible object may have a host-realm prototype chain without bridge interposition). See ATTACKS.md Category 33 and test/ghsa/GHSA-6j2x-vhqr-qr7q/.
  • GHSA-rp36-8xq3-r6c4 — NodeVM builtin denylist bypass via process and inspector/promises. The exact-match denylist in lib/builtin.js missed two host-passthrough families: process (whose getBuiltinModule(name) reloads any core module regardless of the embedder's allow/deny configuration) and inspector/promises (whose Session().post('Runtime.evaluate', ...) evaluates attacker JS in the host realm). Structural fix promotes the check to family-prefix via isDangerousBuiltin(key), strips the node: URL prefix, and adds process to the dangerous set — enforced at both BUILTIN_MODULES source and addDefaultBuiltin. Supersedes GHSA-947f-4v7f-x2v8. Adds Defense Invariant #13. See ATTACKS.md Category 21 (extended) and test/ghsa/GHSA-rp36-8xq3-r6c4/.
  • GHSA-r9pm-gxmw-wv6p — NodeVM builtin: ['*'] wildcard exposed Node's undocumented underscored network builtins (_http_client, _http_server, the _http_* / _tls_* / _stream_* siblings), letting sandbox code make outbound HTTP requests and open listening sockets even when the documented -http/-https/-net/-tls exclusions were used — SSRF-class capability bypass (CVSS 8.6). Structural fix in lib/builtin.js: BUILTIN_MODULES filter now excludes any name starting with _, so '*' expands only to documented public builtins; explicit opt-in, mock, and override paths remain functional. See ATTACKS.md Category 34 and test/ghsa/GHSA-r9pm-gxmw-wv6p/.
  • GHSA-9g8x-92q2-p28f — NodeVM builtin allowlist surfaced four process-wide observability builtins (diagnostics_channel, async_hooks, perf_hooks, v8) that read state from the entire host process rather than the sandbox: HTTP IncomingMessage headers (incl. auth tokens) via diagnostics_channel.subscribe, embedder AsyncLocalStorage context via async_hooks.executionAsyncResource, embedder performance.mark labels via perf_hooks, and the full V8 heap via v8.getHeapSnapshot / v8.queryObjects. Fix in lib/builtin.js: extends DANGEROUS_BUILTINS with the four names, reusing the existing two-layer enforcement (BUILTIN_MODULES filter + addDefaultBuiltin rejection, family-prefix and node:-normalised via isDangerousBuiltin). mock/override escape hatches preserved. See ATTACKS.md Category 35 and test/ghsa/GHSA-9g8x-92q2-p28f/.

Upgrade notes

  • If you constructed NodeVM({ nesting: <truthy> }) without an explicit require config object, new NodeVM(...) now throws (GHSA-m4wx-m65x-ghrr). This covers every shape that previously silently produced a vm2-only resolver: omitting require entirely, or setting it to any falsy value (false/undefined/null/0/'') or any truthy non-object value (true/number/string/symbol/function); and also any truthy nesting value, not only nesting: true (1/'yes'/{}/[]/function). Either drop nesting, or pass an explicit require config object (e.g. require: { builtin: [] }) to acknowledge that vm2 will be requireable from inside the sandbox. The error message is actionable and links to the README hardening section.

[3.11.3]

Patch release — no API changes.

Security fix

  • GHSA-248r-7h7q-cr24 — async generator yield*-return thenable exception capture. Calling i.return(thenable) on an async generator delegating to a no-return inner iterator let V8's PromiseResolveThenableJob capture synchronous throws from the thenable's .then and surface them to sandbox code as iterator results — bypassing both the transformer's catch instrumentation and the globalPromise.prototype.then rejection sanitiser. Two-layer defense on %AsyncGeneratorPrototype%.next/.return/.throw in lib/setup-sandbox.js: every iterator-result promise routes value and rejection through handleException, and every thenable argument is replaced with a sandbox-realm wrapper whose .then is a fixed safeThen that sanitises sync throws and recursively re-wraps any nested thenable handed to resolve(...). When safeThen reads value.then and it is non-function, the wrapper always resolves with a {__proto__: null} shadow so V8's re-read of .then cannot observe attacker-controlled values — closing every counting/self-replacing-getter TOCTOU variant. Trade-off: identity is not preserved for non-thenable values passed to i.return(x). ATTACKS.md Category 29.

[3.11.2]

Three advisories closed. Patch release — no API changes.

Security fixes

  • GHSA-2cm2-m3w5-gp2f — Internal state reachable via computed property access on globalThis. The previous fix (GHSA-wp5r-2gw5-m7q7) tightened the transformer's identifier-rejection but left globalThis['VM2_INTERNAL_STATE_DO_NOT_USE_OR_PROGRAM_WILL_FAIL'] and every reflective probe of the global object (bracket access, Reflect.get, Object.getOwnPropertyDescriptor, Object.getOwnPropertyNames enumeration) returning the live state object — the transformer is a syntactic gate and cannot see through dynamic property keys. Structural fix: the bootstrap script (vm.js's setupSandboxScript source) now declares let VM2_INTERNAL_STATE_DO_NOT_USE_OR_PROGRAM_WILL_FAIL at the script's top level, which lands the binding in the context's [[GlobalLexicalEnvironment]] — reachable as a bare identifier from every script (so transformer-emitted catch handlers still resolve), but absent from globalThis's own-property table (so every computed-key probe returns undefined). The defineProperty install in setup-sandbox.js is removed entirely; the bootstrap IIFE assigns into the outer let instead. Supersedes GHSA-wp5r-2gw5-m7q7's identifier-only mitigation by closing the entire computed-key class. ATTACKS.md Category 27.
  • GHSA-9vg3-4rfj-wgcm — Sandbox breakout via null-proto throw / handleException. The post-GHSA-mpf8 hardening switched handleException and globalPromise.prototype.then onFulfilled to wrap caught/resolved values with bridge.from() for "symmetry". from() builds a sandbox-side proxy whose target the bridge treats as host-realm; calling it on a sandbox-realm null-proto value ({__proto__: null} thrown or Promise.resolve-d by sandbox JS) produced a proxy whose set trap unwrapped sandbox proxies of host references (e.g. Buffer.prototype.inspect) back to their raw host originals and stored them on the underlying sandbox object — readable via the original sandbox reference and pivot to host Function constructor → RCE. Three callsites in lib/setup-sandbox.js reverted to ensureThis() semantics; the host-Promise rejection sanitizer composes from() outside handleException so the GHSA-mpf8 invariant (host null-proto rejection values must reach sandbox callbacks bridge-wrapped) is preserved. ATTACKS.md Category 26.
  • GHSA-9qj6-qjgg-37qq — sandbox breakout via the species-defense helper neutralizeArraySpeciesBatch. The helper appended saved-state records to a fresh [] literal that — being allocated by the sandbox-side bridge closure — inherited sandbox Array.prototype. A sandbox-installed setter on Array.prototype[N] therefore captured the next saved[saved.length] = c write and exposed c.arr (a host-realm proxy) directly to attacker code, leading to host Function extraction and RCE. Fixed in lib/bridge.js by writing every saved-state entry through thisReflectDefineProperty so the appended slot is an own data property and no Array.prototype[N] setter is ever invoked while the bridge holds raw saved state. ATTACKS.md gains a new Defense Invariant ("Bridge-internal containers must not invoke sandbox code") codifying the cross-cutting principle.

[3.11.1]

... (truncated)

Commits
Maintainer changes

This version was pushed to npm by GitHub Actions, a new releaser for vm2 since your current version.


Dependabot compatibility score

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


Dependabot commands and options

You can trigger Dependabot actions by commenting on this PR:

  • @dependabot rebase will rebase this PR
  • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
  • @dependabot show <dependency name> ignore conditions will show all of the ignore conditions of the specified dependency
  • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
  • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
  • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    You can disable automated security fix PRs for this repo from the Security Alerts page.

Bumps [vm2](https://github.com/patriksimek/vm2) from 3.9.19 to 3.11.5.
- [Release notes](https://github.com/patriksimek/vm2/releases)
- [Changelog](https://github.com/patriksimek/vm2/blob/main/CHANGELOG.md)
- [Commits](patriksimek/vm2@3.9.19...v3.11.5)

---
updated-dependencies:
- dependency-name: vm2
  dependency-version: 3.11.5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
@dependabot dependabot Bot added dependencies Pull requests that update a dependency file javascript Pull requests that update javascript code labels May 18, 2026
@Spiral-Memory Spiral-Memory merged commit 476bf0b into develop May 18, 2026
5 checks passed
@dependabot dependabot Bot deleted the dependabot/npm_and_yarn/vm2-3.11.5 branch May 18, 2026 19:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file javascript Pull requests that update javascript code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant