v3.11.0
Coordinated security release closing 13 advisories, plus a new bufferAllocLimit option and a realpath() method on the FileSystem adapter contract. Minor version bump because of the new public option and the FileSystem contract addition; no incompatible changes to the existing public API surface.
Embedders running untrusted code should upgrade. Several of the advisories close full sandbox-escape RCE primitives.
What's Changed
Security fixes
- GHSA-grj5-jjm8-h35p — Array species self-return sandbox escape (RCE)
- GHSA-v37h-5mfm-c47c — Handler reconstruction via
util.inspectleak (RCE) - GHSA-qcp4-v2jj-fjx8 — Trap method on leaked handler with forged target (RCE)
- GHSA-47x8-96vw-5wg6 — Cross-realm symbol extraction from host objects (RCE)
- GHSA-55hx-c926-fr95 — Promise structural-leak / SuppressedError / AggregateError sanitisation (RCE)
- GHSA-vwrp-x96c-mhwq — Host intrinsic prototype pollution via bridge write traps
- GHSA-947f-4v7f-x2v8 — NodeVM builtin allowlist bypass via host-passthrough builtins (RCE)
- GHSA-hw58-p9xv-2mjh — Promise executor unhandled rejection host-process DoS
- GHSA-6785-pvv7-mvg7 — Unbounded
Buffer.alloc(N)host-heap DoS - GHSA-mpf8-4hx2-7cjg — Host Promise
.then(onFulfilled)/ sanitiser-callback null-proto unwrapping (RCE) - GHSA-v27g-jcqj-v8rw —
CallSitehost-frame information disclosure viaprepareStackTrace - GHSA-wp5r-2gw5-m7q7 — Transformer fast-path bypass via
with/INTERNAL_STATE_NAME/ unicode-escape identifier (RCE) - GHSA-cp6g-6699-wx9c — NodeVM
require.rootsymlink bypass (RCE)
Plus two related hardenings discovered during pre-release red-team:
trace_eventsadded to the dangerous-builtins denylist —createTracing({categories: [Proxy<Array>]})triggered a C++ assertion that aborted the host process.wasiadded to the denylist — experimental syscall surface (filesystempreopens, host clock/random, network) too broad for default'*'exposure.
New options
bufferAllocLimit(VM, NodeVM) — non-negative number orInfinity. Caps individualBuffer.allocfamily requests from inside the sandbox. Default:Infinity(fully backwards-compatible). Embedders running untrusted code should opt into a finite cap as part of layered DoS defense.
FileSystem contract
DefaultFileSystem.realpath()andVMFileSystem.realpath()added.require.rootboundary checks now canonicalise candidate paths viarealpathbefore the prefix check, closing CWE-59 (symlinks inside the allowed root pointing outside it). Especially relevant for pnpm / npm-workspaces /npm linklayouts where everynode_modulesentry is a symlink by design.
Upgrade Notes
- Custom
fsadapters withrequire.rootmust implementrealpathSync(orrealpath()on a fully customFileSystemclass). Without it,new NodeVM({require: {root, fs: customAdapter}})now throws aVMErrorat construction citing GHSA-cp6g-6699-wx9c. Defaultfsusers are unaffected. - Embedders running untrusted async code should install a host-side
unhandledRejectionhandler. The GHSA-hw58 fix closes synchronous executor throws but cannot reach async-function / async-generator /await usingrejection paths (V8 creates rejection promises via the realm's intrinsicPromise). See Hardening recommendations. - Embedders in memory-constrained environments should opt into a finite
bufferAllocLimit(e.g.32 * 1024 * 1024).
Documentation
- New README Hardening recommendations section.
docs/ATTACKS.mdupdated through Category 24, plus new Defense Invariants and Category Entry Format sections.
Full Changelog: v3.10.5...v3.11.0