CVE-2026-92962
lowPriorität · verfolgen · 0EPSS 0.002 · 5. PerzentilDERUUSEPSS · bewertet 2026-10-27
vm2 is a sandbox for running untrusted JavaScript. In vm2 versions up to and including 3.11.3, the defaultSandboxPrepareStackTrace function in lib/setup-sandbox.js builds its output array using prototype-walking index assignment (lines[lines.length] = value) rather than a prototype-bypassing define-property primitive. Because this bridge-internal array is allocated in the sandbox realm, code inside the sandbox can install an accessor on Array.prototype for the relevant index; the accessor is then invoked whenever the sandbox reads error.stack (or otherwise triggers Error.prepareStackTrace), allowing sandbox code to observe and intercept each stack-trace line written by the bridge. The same pattern is used in the error-handling (catch) branch. The values written are formatted strings only, so the practical impact is limited to an information side channel and a violation of vm2's bridge-container defense invariant rather than a sandbox escape; the vendor rates the issue Low. The issue is fixed in vm2 3.11.4, which installs each entry as an own data property via Reflect.defineProperty.
cvss
Technischer Schweregrad, 0–10. Eine Zeile je Quelle.
Basiswert 0–10 · höher = schwerwiegender · Vektor überfahren zum Auflösen
SSVC
Eine Handlungsentscheidung — aus Ausnutzung und Auswirkung.
schwächen
Die CWE-Schwächeklassen, zu denen dies gehört.
betroffene Produkte (4)
Betroffene Produkte und Versionsbereiche.
Advisories (2)
Hersteller- und Ökosystem-Meldungen dazu.
- WID-SEC-W-2026-1583vm2: Mehrere SchwachstellenDeutsch2026-05-18csaf · cert_bundDE
Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in vm2 ausnutzen, um beliebigen Programmcode auszuführen, Sicherheitsmaßnahmen zu umgehen, Daten zu manipulieren und vertrauliche Informationen offenzulegen.
- GHSA-q3fm-4wcw-g57xvm2 setup-sandbox.js violates Defense Invariant #11 in stack-trace formatter2026-05-29ghsa · osvUS
## Summary `defaultSandboxPrepareStackTrace` in `lib/setup-sandbox.js` (lines 605, 607) appends to a fresh sandbox-realm `lines = []` via `lines[lines.length] = value`. This is the exact invariant-violating pattern that GHSA-9qj6-qjgg-37qq (commit ca195f0, 2026-05-01) just patched in `neutralizeArraySpeciesBatch` and codified as Defense Invariant #11 ("Bridge-internal containers must not invoke sandbox code"). A sandbox-installed `Array.prototype[N]` setter fires during the bridge's safe-default stack-trace formatting and observes / intercepts each appended line. ## Details The post-9qj6 audit note in `docs/ATTACKS.md` (line 2111) states: > Equivalent pattern elsewhere in the bridge: audited; thisFromOtherArguments, otherFromThisArguments, and every other index-write site already use thisReflectDefineProperty or otherReflectDefineProperty. neutralizeArraySpeciesBatch was the lone outlier. The audit is scoped to `lib/bridge.js`. `lib/setup-sandbox.js` was not covered. `defaultSandboxPrepareStackTrace` (added under post-#563 hardening for GHSA-v27g) constructs a sandbox-realm `[header]` array and appends each frame via the prototype-walking index assignment: ``` // lib/setup-sandbox.js, lines 601-610 const lines = [header]; for (let i = 0; i < callSites.length; i++) { try { lines[lines.length] = ' at ' + callSites[i]; } catch (e) { lines[lines.length] = ' at <error formatting frame>'; } } return lines.join('\n'); ``` This function runs every time sandbox code reads `error.stack` (or any path that triggers `Error.prepareStackTrace`). At the time it runs, user code has already had the opportunity to install a setter on `Array.prototype[N]`. Because `lines` starts at length 1, the first iteration writes index 1; if `lines[1]` has no own data property, V8 walks the prototype chain and invokes the sandbox-controlled setter. The currently-assigned value is the string `' at ' + callSites[i]` (the wrapped `CallSite` class's safe `toString()` returns `'CallSite {}'`), which limits the immediate impact to a side channel, not an RCE pivot. The concern is structural rather than exploit-today: - The just-codified Defense Invariant #11 explicitly requires that any list, set, or map allocated for the bridge's exclusive use must read and write through identity-stable, prototype-bypassing primitives. This site does not. - The `catch` branch at line 607 also uses the same pattern, so a sandbox getter that throws on `callSites[i]` access still routes its retry write through the prototype chain. - A future change that makes the appended slot value an object holding a host-realm reference (for example, an enriched frame record) would re-introduce the exact GHSA-9qj6 attack shape against this codepath. The fix is mechanical and mirrors the GHSA-9qj6 patch: install entries via `localReflectDefineProperty` so each appended slot is an own data property and the prototype-chain setter is bypassed. ```javascript // Suggested patch (sketch) let linesLen = 1; function append(s) { localReflectDefineProperty(lines, linesLen, { __proto__: null, value: s, writable: true, enumerable: true, configurable: true, }); linesLen++; } for (let i = 0; i < callSites.length; i++) { try { append(' at ' + callSites[i]); } catch (e) { append(' at <error formatting frame>'); } } ``` The same pattern at `callSiteGetters[callSiteGetters.length] = {...}` (line 649) runs only at sandbox setup, before user code can install setters, so it is safe today. Converting it for symmetry would be cheap and forward-compatible. ## PoC vm2 v3.11.2, Node v24. ```javascript const { VM } = require('vm2'); const result = new VM().run(` var observed = { setterFired: false, capturedValue: null, indexFired: null }; Object.defineProperty(Array.prototype, 1, { configurable: true, set(value) { observed.setterFired = true; observed.indexFired = 1; observed.capturedValue = typeof value === 'string' ? value.slice(0, 40) : typeof value; }, get() { return undefined; } }); var e = new Error('x'); e.stack; observed; `); console.log(result); // { // setterFired: true, // capturedValue: ' at CallSite {}', // indexFired: 1 // } ``` Sandbox code observed and intercepted the bridge-internal write to `lines[1]`. Repeating the PoC with the setter installed at multiple indices (0, 1, 2, ...) captures every frame the formatter would otherwise return. ## Impact Hardening / Defense Invariant #11 violation. No direct sandbox escape on the current codebase: the value passed to the setter is a primitive string after the wrapped `CallSite.toString()`, so attacker-controlled code does not gain a host-realm reference from the setter argument alone. The GHSA-9qj6 entry's "Considered Attack Surfaces" note states the audit covered `lib/bridge.js` index-write sites; this filing reports the equivalent pattern in `lib/setup-sandbox.js` so the invariant is uniform across the bridge boundary and future enrichments of the appended record cannot regress into the GHSA-9qj6 shape.
auch bekannt als (1)
Weitere Namen und Kennungen dieser Entität.
quellen
Welche Quellen diesen Datensatz belegen und wann.
Referenzen (2) nvd
Externe Belege — Patches, Meldungen, Analysen.
Angreifer nutzen Schwachstellen wie diese gegen im Internet exponierte Dienste aus. Sehen Sie mit einem kostenlosen Passiv-Scan, was exponiert ist.
Kostenloser Scan