CVE-2026-92944
KrytyczneCVSS 9.8Streszczenie
vm2 w wersjach od 3.10.2 do 3.11.6 zawiera podatność na ucieczkę z sandboxa w Node.js 26, gdzie Promise.prototype.finally() omija zabezpieczenia vm2 z powodu nieaktualnego protectora PromiseThenLookupChain w V8 14.6. Atakujący mogą to wykorzystać, tworząc funkcję asynchroniczną zwracającą Promise z kontrolowanym przez atakującego konstruktorem Symbol.species, co pozwala dotrzeć do konstruktora Function hosta i obiektu process w celu wykonania dowolnego kodu.
Ocena ryzyka
Ucieczka z sandboxa umożliwia wykonanie dowolnego kodu w kontekście hosta, co prowadzi do pełnej kompromitacji procesu Node.js i systemu.
Rekomendacja
Zaktualizuj vm2 do wersji 3.11.7, która naprawia obejście ochrony Promise.prototype.finally() na Node.js 26.
Inne podatności w vm2
Zobacz wszystkie- CVE-2026-92963Średnie
W vm2 w wersjach przed 3.11.2 nieprawidłowo ograniczono dostęp do globalnej zmiennej VM2_INTERNAL_STATE_DO_NOT_USE_OR_PROGRAM_WILL_FAIL. Atakujący może uzyskać dostęp do tego wewnętrznego obiektu stanu poprzez globalThis i pozyskać wrażliwe elementy wewnętrzne piaskownicy.
- CVE-2026-92961Wysokie
vm2 przed wersją 3.11.6 nie egzekwuje limitu bufferAllocLimit dla konstruktorów ArrayBuffer, SharedArrayBuffer i TypedArray, co pozwala atakującym alokować dowolną pamięć hosta. Atakujący mogą obejść limit alokacji bufora, używając tych wbudowanych funkcji V8 do wyczerpania pamięci procesu hosta i wywołania warunków braku pamięci.
- CVE-2026-92959Wysokie
vm2 przed wersją 3.11.8 nie egzekwuje w pełni opcji allowAsync: false w VM i NodeVM. Mimo że localPromise.prototype.then jest zastąpione procedurą rzucającą błąd 'Async not available', statyczne metody Promise w sandboxie (Promise.resolve, Promise.all, Promise.race, Promise.any, Promise.allSettled) nadal asymilują dostarczone przez atakującego thenable, co pozwala na zaplanowanie pracy po zakończeniu VM.run() lub NodeVM.run() i poza skonfigurowanym limitem czasu.
- CVE-2026-92958Wysokie
vm2 do wersji 3.11.6 zawiera obejście listy zablokowanych modułów wbudowanych w NodeVM. Gdy osadzający używa symbolu wieloznacznego builtin wraz z wpisami negatywnymi (np. require: { builtin: ['*', '-fs', '-child_process'] }), wpisy negatywne są dopasowywane po dokładnej nazwie modułu, więc -fs usuwa tylko moduł fs, a nie jego podścieżki, takie jak fs/promises. Kod w sandboxie może wywołać require('fs/promises') lub require('node:fs/promises') i uzyskać dostęp do API systemu plików opartego na obietnicach.
- CVE-2026-92954Wysokie
vm2 w wersjach od 3.10.0 do 3.11.7 nie oznacza jako obsłużonych obietnic zwracanych z realm hosta do sandboxa na granicy mostu. Tylko obietnice utworzone wewnątrz sandboxa są opakowywane w procedurę pochłaniającą odrzucenie, a most instaluje sanitizery odrzuceń po stronie hosta tylko wtedy, gdy kod sandboxa wywoła .then/.catch/.finally. W rezultacie kod w sandboxie może wywołać funkcję hosta zwracającą odrzuconą obietnicę i zignorować wartość zwracaną, pozostawiając obietnicę hosta nieobsłużoną, co powoduje zakończenie procesu hosta przez domyślne zachowanie Node.js.
- CVE-2026-92952Średnie
W vm2 w wersjach od 3.11.4 do 3.11.6 niekompletnie filtrowano zarejestrowane wewnętrzne symbole Node.js na granicy piaskownicy. Filtry w lib/setup-sandbox.js oraz sprawdzenia symboli i pułapki zapisu w lib/bridge.js używają stałej listy znanych niebezpiecznych symboli, pomijając nodejs.stream.disturbed i nodejs.stream.errored, które są eksponowane na prototypach WebStream w nowszych wersjach Node.js. Gdy osadzający udostępnia obiekt WebStream i moduł stream/web piaskownicy, kod piaskownicy może uzyskać prawdziwe symbole hosta i użyć ich jako kluczy zapisu na obiektach strumieni hosta, uszkadzając widoczny dla hosta stan strumienia. Może to obejść logikę hosta opartą na publicznych pomocnikach stanu strumienia Node.js. Nie jest to prymityw wykonania kodu hosta w zgłoszonym dowodzie podatności. To niekompletna poprawka wcześniejszego problemu filtrowania symboli nodejs.*. Naprawiono w vm2 3.11.7.
- CVE-2026-92950Wysokie
Podatność w narzędziu CLI vm2 (przed wersją 3.11.7) umożliwia ucieczkę z piaskownicy i wykonanie dowolnego kodu w procesie Node.js hosta. Atakujący może dostarczyć złośliwy plik skryptu, który używa require(__filename) do ponownego wykonania siebie w środowisku hosta, omijając izolację piaskownicy i uzyskując dostęp do modułów takich jak fs i child_process.
- CVE-2026-92949Średnie
W vm2 w wersjach od 3.9.6 przed 3.11.7 nieprawidłowo ograniczono dostęp do właściwości akcesorów na zamrożonych obiektach, co pozwala skryptom w piaskownicy obejść zabezpieczenia vm.freeze() i vm.readonly(). Atakujący może użyć Object.getOwnPropertyDescriptor() lub __lookupSetter__() do wyodrębnienia i wywołania setterów obiektów hosta bezpośrednio, modyfikując właściwości oznaczone przez osadzającego jako tylko do odczytu.
- CVE-2026-92945Średnie
vm2 w wersjach przed 3.11.7 zawiera podatność obejścia listy dozwolonych modułów w funkcji isPathAllowedForModule, która używa dopasowania prefiksu ciągu znaków zamiast porównania z granicami ścieżki. Atakujący może uzyskać dostęp do niedozwolonych pakietów dzielących prefiks z modułami z listy dozwolonych, wykonując względne require z dozwolonych pakietów przy wyłączonym ładowaniu tranzytywnym.
- CVE-2026-92942Wysokie
W wersjach vm2 ≤ 3.11.6 opcja VM({ timeout }) nie jest egzekwowana dla kodu wykonywanego poza synchronicznym wywołaniem VM#run(). Sandboxowany kod może zarejestrować wywołanie zwrotne FinalizationRegistry i po zwolnieniu obiektu zablokować pętlę zdarzeń hosta na nieograniczony czas, powodując denial of service.
Oryginalny opis (angielski, źródło NVD)
vm2 versions 3.10.2 through 3.11.6 contain a sandbox escape vulnerability on Node.js 26 where Promise.prototype.finally() bypasses vm2's wrapper protections due to a stale PromiseThenLookupChain protector in V8 14.6. Attackers can exploit this by creating an async function that returns a Promise with an attacker-controlled constructor Symbol.species, allowing them to reach the host Function constructor and process object for arbitrary code execution.

