vm2 sandbox escape: analysis of three critical CVSS 10.0 shoots in Node.js

Depov

Moderator
Staff member
MODERATOR
ULTIMATE
SUPREME
PREMIUM
MEMBER
Joined
Feb 18, 2025
Messages
345
Reaction score
508
Deposit
0$
Thirteen CVE with a score of 9.0 to 10.0 for the first half of 2026 - in one library, which the continent marked deprecated in 2023. According to The Hacker News, each leads to the execution of arbitrary code on the host system. Three of them, CVE-2026-43997, CVE-2026-44005 and CVE-2026-44006 - scored a maximum score of 10.0 and show three fundamentally different primitive escape from the sandbox: a leak of host Object, prototype pollution through bridge proxy and injection through BaseHandler.getPrototypeOf. I analyze each individually and show why the proxy model of insulation vm2 is not a wall, but a curtain.
Business logic of attack: why break the vm2 sandbox
vm2 - npm-package to run untrusted JavaScript in an isolated Node.js environment. According to Endor Labs, the library is gaining more than a million weekly downloads, although the mainstreamer marked the project back in 2023 as a deprecated: "contains critical security issues and should not be used for production""Contains critical elements of safety and should not be used for production purposes".
Escape from the Node.js sandbox turns the execution of JavaScript inside vm2 into a full-fledged RCE on a host system. For AI agents, as Kodem Security notes, the chain looks like: prompt injection -> malicious JS in sandbox -> vm2 sandbox escape -> shell on the host. CISA, via the ADP-Vulnrichment program, classifies all three CVE as automatable with total technical impact (SSVC Decision: Track*). The PoC code exists for each of the three.

Location in the Attack Chain: Initial Access (T1190, Exploit Public-Facting Application) -> Execution (T1059.007, JavaScript) -> Privilege Escalation (T1611, Escape to Host) The code enters vm2 through user input, LLM generation or a plug-in system - then one of the three primitives described below is enough for the full compromising the host.
Insulation model vm2: proxy wraps and their limits
Adjacent requirements for reproduction
• Node.js: v18+ (for playback CVE-2026-43997, CVE-2026-44005, CVE-2026-44006)
• NPm-pack vm2: version up to 3.10.5 inclusive (all three CVE fixed at 3.11.0)
• OS: Linux, macOS or Windows - vm2 platform-independent
• RAM: Standard requirements of Node.js (from 256 MB)
• Context: only a laboratory environment without access to data
vm2 builds insulation on two mechanisms that are entirely living at the JavaScript level. The first is the code transformer: it is an injector handleException() in catch-clays to intercept host-ill errors. The second is the bridge proxy: every object crossing the sandbox border <-> host, turns into Proxywhich intercepts appeals to properties and methods. According to the plan, the sandbox code never receives a direct link to the host object - only to its proxy copy.

The problem is that both mechanisms work entirely in userland JavaScript. No V8 Isolates (separate heaps of memory), no OS-primites insulation (namespaces, seccomp). Any error in the logic of proxying, processing exceptions or bypass the prototype chain gives the attacker a direct link to a host object. And from a host-object to Function constructor - exactly two steps along the chain obj.constructor.constructor.

vm2 closed such errors by point patches since 2022: CVE 2022-36067 (CVSS 10.0, EPSS 0.4787 - Top 5%), CVE-2023-29017 (CVSS 10.0, EPSS 0.6319 - Top 1%), CVE-2023-30547 (CVSS 9.8, EPSS 0.7209 - Top 1%). Each time the fix closed one specific vector - and each time was the next. The May Wave of 2026 is a continuation of this endless cycle.
CVE-2026-43997: leakage host Object via Symbol
CVSS: 10.0 (CRITICAL) - AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
CWE: CWE-94 (Code Injection), CWE-653 (Improper Isolation or Compartmentalization)
Affected versions: npm vm2 up to 3.11.0 (according to OSV.dev: introduced 0, fixed 3.11.0)
EPSS: 0.0098 (percentile 57.94%)

Essence: sandbox code receives a direct link to the host Object - not on a proxy copy, but to a real Object from the host-context. According to the NVD, one of the methods of operation is a challenge HostObject.getOwnPropertySymbols() to receive Symbol(nodejs.util.inspect.custom).

Why it's bad: Symbol(nodejs.util.inspect.custom) - the internal symbol of Node.js for custom series of objects. If you see it from sandbox, then you work with a real host object, not with a proxy. Next Next Up Standard Chain: Host Object -> Object.constructor -> Function -> arbitrary code in host-context.

CWE-653 (Improper Isolation) - Root cause: the insulation mechanism vm2 does not prevent the leakage of host Object in the sandbox-context. CWE-94 (Code Injection) - consequence: the attacker constructs arbitrary code through Function constructor. The researcher c0rydoras, to which The Hacker News attributes the discovery of this CVE, demonstrated a full chain from receiving host Object to RCE.

Preconditions and limitations: You need the ability to perform arbitrary JavaScript inside vm2 sandbox (VM or NodeVM class). If the application filters the input code before the transfer to vm2 (AST analysis, whitelist functions), the vector can be blocked until the vulnerability path is reached. In practice, most vm2 defores vm2 do not use pre-sandbox filtration - this is the meaning of using the sandbox. Why set up an AST parser if you supposedly sandbox?
CVE-2026-44005: prototype pollution through bridge proxy
CVSS: 10.0 (CRITICAL) - AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:H/A:H
CWE: CWE-94 (Code Injection), CWE-1321 (Improper Control of Modification of Object Prototype Attributes Prototype Pollution), CWE-653 (Improper Isolation)
Affected versions: npm vm2 from 3.9.6 to 3.10.5 (according to OSV.dev)
EPSS: 0.0084 (percentile 53.60%)

This vulnerability is different from the rest of the shoots - the attacker does not receive direct RCE through Function constructor, and host-prototypes mutates directly from the sandbox code. Pay attention to CVSS-vector: C:N/I:H/A:H - confidentiality is not directly affected, but integrity and accessibility - in full.

According to the description of NVD: vm2-bridge exhibits mutable proxy for real host-prototypes (Object.prototype, Array.prototype, Function.prototype) and proxys records from sandbox to host through otherReflectSet() and otherReflectDefineProperty(). Sandbox code writes in Object.prototype - and this mutation goes through the bridge into a real host-context.
CWE-1321 (Prototype Pollution) - accurate description of mechanics. There is a fundamentally different approach: the attacker does not need child_process.exec() directly. JavaScript sandbox bypass through prototype pollution in host-context beats Everything Node.js-process - other modules, middleware, authorization verification. In combination with CVE-2026-43997 or CVE-2026-44006 It turns out a full chain: first, the prototype pollution is possible to prepare the environment, then a direct escape for RCE. It's beautiful, if you look at the attacker.

Restrictions: Operation requires a version vm2 starting at 3.9.6 (before it, bridge mechanism worked differently). If the app is running vm2 in a separate Worker Thread with --frozen-intrinsics, the prototype mutation may be partially limited - but I have not met such a configuration in the market.
CVE-2026-44006: arbitrary prototypes via getPrototypeOf
CVSS: 10.0 (CRITICAL) - AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
CWE: CWE-94 (Code Injection), CWE-914 (IMproper Control of Dynamically-Identified Variables)
Affected versions: npm vm2 up to 3.11.0 (according to OSV.dev: introduced 0, fixed 3.11.0)
EPSS: 0.0081 (percentile 52.77%)

The third primitive attacks the mechanism of proxy in the forehead. According to the description of NVD: sandbox-code gets to the method BaseHandler.getPrototypeOfwhich returns arbitrary prototypes from host-context.

BaseHandler - internal handle vm2, control Proxy-trafficers for all objects crossing the sandbox <-> host border. If the attacker gets to getPrototypeOf this handler, he gets direct access to the prototype chain of host objects - without proxy and sanitization. Bypassing JavaScript is based on the mechanisms of prototy language inheritance. The irony is that vm2 tries to control exactly the mechanisms that are used to bypass it.

CWE-914 (IMproper Control of Dynamically-Identified Variables) - root problem: vm2 does not control access to internal variables (BaseHandler), which are identified dynamically through the prototype chain. The attacker uses the mechanisms of JavaScript itself (prototype chain traversal) to access internal insulation components.

The researcher c0rydoras also found this CVE (according to The Hacker News) - indicating a system audit of the proxy model vm2, not random finds. When one person pulls out three CVSS 10.0 from one library is not luck, it is a methodical analysis of architecture.
Vulnerability classification: CWE, CWE-913, CWE-74 and MITRE AT&CK
CWE Hierarchy for CVE Triple
Three CVE combined root weakness CWE-94 (Code Injection), but each adds its own specific CWE:
In the CWE hierarchy, all three fall under two parent classes that accurately describe the nature of vm2 shoots:

CWE-913 (Improper Control of Dynamically-Managed Code Resources) - CWE-94 daughters for CWE-913 (Beit-Of communication). The library does not control the dynamically managed code resources - prototypes, designers, symbols - to which sandbox code gets access. CWE-913 is clearly assigned a kinship CVE-2026-22709 (CVSS 9.8) and historical CVE 2022-36067, CVE-2023-29017, CVE-2023-29199. The same root weakness, different ways of operation.

CWE-74 (Improper Neutralization of Special Elements in Output Used by a Downstream Component) - second parental class CWE-94. The attacker forms "special elements" (adversions to prototypes, symbols, internal handlers) that vm2 does not neutralize when crossing the sandbox -> host boundary. CWE-74 is clearly appropriated CVE-2023-30547 (CVSS 9.8, EPSS 0.7209 - Top 1%), confirming the total pattern.
Mapping on MITRE ATT&CK and EPSS-forecast
The chain of attack through the escape from the sandbox Node.js:
1. Initial Access - T1190 (Exploit Public-Facting Application): code enters vm2 via web interface, API or LLM generation
2. Execution - T1059.007 (JavaScript): Malicious JS is running inside vm2
3. Privilege Escalation - T1611 (Escape to Host): one of the three primitives punches the border of sandbox
4. Post-Explotication - T1106 (Native API): access to child_process, fs, netthrough host-context
EPSS for July 2026: CVE-2026-43997 - 0.0098 (percentile 57.94%), CVE-2026-44005 - 0.0084 (percentile 53.60%), CVE-2026-44006 - 0.0081 (percentile 52.77%). So far, the indicators are moderate. For comparison: CVE-2023-30547 with similar mechanics sandbox escape scored EPSS 0.7209 (Top 1%), and CVE-2023-29017 - 0.6319 (Top 1%). It took time for both to appear in public exploit kits. The current trajectory indicates the growth of EPSS as the PoC code spreads – and I wouldn’t wait.
 
Top Bottom