v3.11.8
Six advisories closed. Patch release — no API changes for valid configurations, with a few narrow observable behaviour changes (see Upgrade Notes).
What's Changed
Security fixes
- GHSA-3vgf-8m4q-q4qr (dup: GHSA-59g5-pmg6-5gr4) — the default
VM's protected-intrinsic inventory omitted the binary-data and iterator families (ArrayBuffer/SharedArrayBuffer/DataView/ everyTypedArrayand%TypedArray%.prototype, plus the array/string/map/set/regexp-string iterator prototypes and%IteratorPrototype%). BecauseBufferextendsUint8Array, a proto-walk from a hostBufferreached those unprotected host prototypes and polluted them globally — corrupting every host-realm typed array and iterator (host-state corruption). - GHSA-88hf-g992-jg85 — a NodeVM in its default
console: 'inherit'configuration was escapable: sandbox code extracted the raw hostObject.prototype.__proto__getter (never classified dangerous like the setter), climbedconsole._stdout's host prototype chain toEventEmitter.prototype, overwroteemit, and had the host invoke it withthis === process— full host RCE. - GHSA-f8gf-w286-fmq2 —
allowAsync: falsecould be bypassed through Promise thenable assimilation:Promise.resolve/all/race/any/allSettled/try,new Promise(r => r(thenable)),withResolvers().resolve,Array.fromAsync, and the realm-intrinsic Promise base all let V8'sPromiseResolveThenableJobrun an attacker.thenin a microtask afterrun()returned, outside the configuredtimeout. - GHSA-gjq8-xm47-88rc — an embedder-exposed host function (or a host builtin such as
events.once) returning a rejected hostPromisecrashed the entire host process when sandbox code called it and ignored the result: the underlying host promise had no rejection reaction, so Node's defaultunhandledRejectionpolicy tore the process down — a host DoS from one line of untrusted code. - GHSA-r273-hxvj-fxhp — NodeVM exposed host
utilas an unfilteredObject.assign({}, util), soutil.getCallSites()(Node ≥ 22.9) handed the sandbox the host process call stack — absolute paths including vm2's ownlib/and the embedder entrypoint,node:internalframes, function names and line numbers — bypassing the GHSA-v27g host-frame redaction, which only covers sandbox-realm error stacks.getCallSite/setTraceSigInt/ private internals rode the same wholesale copy; thesysalias leaked identically (information disclosure). - GHSA-x965-fc75-jpqh — patch bypass of GHSA-m283-3h24-438v: a host-wrapped
AggregateError/SuppressedErrorrevisited within a singlehandleExceptiontraversal (self-cycle,[shared, shared], mutual cycle) had its raw host proxy returned by the cycle memo and re-embedded into the rebuilterrors[], delivering a live host reference to sandboxcatchcode — host RCE on the exact channel Defense Invariant #3 promises to sanitize.
Documentation
docs/ATTACKS.mdgains Categories 49 (revisited error-carrier cycle memo), 50 (host prototype-chain climb via the raw__proto__getter), 51 (allowAsync: falsethenable assimilation) and 52 (hostutilmember auto-forwarding), plus extensions to Categories 20 (protected binary-data / iterator intrinsics) and 22 (ignored host-promise rejection), and matching rows in the "How The Bridge Defends" table.
Upgrade Notes
allowAsync: falseis now strict about thenable assimilation. UnderallowAsync: false, the assimilatingPromisestatic methods (resolve/all/race/any/allSettled/try) andArray.fromAsyncnow throw in the sandbox, and the native Promise base is not constructable from sandbox code. This closes the microtask-after-run()bypass.allowAsync: trueis completely unaffected — no valid async configuration changes.- The sandbox
utilbuiltin is now a vetted allowlist. Host-introspection / host-mutation members —util.getCallSites,util.getCallSite,util.setTraceSigInt, and private internals — are no longer forwarded to the sandbox (nor via the deprecatedsysalias). Documented util members (format,inspect,promisify,callbackify,types,TextEncoder,parseArgs, …) are unchanged. A member Node adds in future no longer auto-enters the sandbox. - Raw host prototype readers are denied delivery. The sandbox can no longer obtain the raw host
Object.prototype.__proto__getter,Object.getPrototypeOf, orReflect.getPrototypeOfto climb a host object's prototype chain. LegitimateObject.getPrototypeOfon a host proxy, and ordinary data/leaf property writes, are unchanged. - No other valid configurations are affected. The intrinsic-prototype protection (GHSA-3vgf), host-promise rejection handling (GHSA-gjq8), and error-sanitization (GHSA-x965) fixes are transparent to correct sandbox code.
Full Changelog: v3.11.7...v3.11.8