Recently added

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.

Recently updated

Two LiteLLM versions published containing credential harvesting malware

After an API Token exposure from an exploited trivy dependency, two new releases of litellm were uploaded to PyPI containing automatically activated malware, harvesting sensitive credentials and files, and exfiltrating to a remote API. Anyone who has installed and run the project should assume any credentials available to litellm environment may have been exposed, and revoke/rotate thema ccordingly.