Krytyczna luka „sandbox escape” w vm2 dla Node.js (CVE-2026-22709) – jak działa i co zrobić natychmiast

securitybeztabu.pl 7 godzin temu

Wprowadzenie do problemu / definicja luki

vm2 to popularna biblioteka do uruchamiania niezaufanego JavaScriptu w „piaskownicy” (sandboxie) w środowisku Node.js. Jej typowy cel to umożliwienie wykonywania kodu użytkownika bez dostępu do systemu plików czy API hosta.

W praktyce okazało się, iż w vm2 wykryto krytyczną podatność typu sandbox escape oznaczoną jako CVE-2026-22709. Pozwala ona napastnikowi uciec z izolacji i wykonać dowolny kod na hoście (RCE) – czyli dokładnie złamać fundamentalne założenie „bezpiecznej piaskownicy”.

W skrócie

  • Identyfikator: CVE-2026-22709
  • Wektor: obejście mechanizmu sanitizacji callbacków dla Promise.then() / Promise.catch()
  • Skutek: sandbox escape → RCE na hoście
  • Wersje podatne: vm2 przed 3.10.2
  • Naprawa: aktualizacja do ≥ 3.10.2 (w praktyce najlepiej do najnowszej wersji z gałęzi 3.10.x)
  • Ocena ryzyka: CVSS 9.8 (Critical) wg CNA (GitHub)

Kontekst / historia / powiązania

vm2 jest szeroko używane m.in. w platformach SaaS pozwalających użytkownikom uruchamiać własne skrypty, runnerach kodu online czy botach/czatbotach. BleepingComputer podaje skalę użycia rzędu 200k+ projektów na GitHub oraz około ~1 mln pobrań tygodniowo w npm.

Jednocześnie vm2 ma historię kolejnych ucieczek z sandboxa. W 2023 r. głośne były m.in. CVE-2023-29017 oraz CVE-2023-30547 – obie klasy „sandbox escape”.
Według BleepingComputer projekt był choćby wstrzymany w 2023 r. z powodu powtarzających się problemów, a później „wskrzeszony” (powrót rozwoju i wersji 3.10.x).

Analiza techniczna / szczegóły luki

Sedno problemu to niekonsekwentna sanitizacja callbacków przypinanych do obietnic (Promises):

  • vm2 sanitizuje callbacki dla swojej „lokalnej” implementacji obietnic (w uproszczeniu: localPromise.prototype.then),
  • ale nie obejmuje tym samym mechanizmem „globalnych” Promise (tj. globalPromise.prototype.then),
  • a ponieważ wartości zwracane z async funkcji są oparte o globalny Promise, atakujący może doprowadzić do wykonania callbacka w sposób umożliwiający wyrwanie się do kontekstu hosta.

W praktyce publicznie pokazano PoC, w którym poprzez manipulację obsługą błędu i uzyskanie dostępu do konstruktorów (np. Function) da się finalnie doprowadzić do uruchomienia polecenia systemowego na hoście (np. przez child_process).

Status poprawek (ważne operacyjnie):

  • wg maintenera podatność była częściowo zaadresowana w 3.10.1,
  • a 3.10.2 „domknęło” fix tak, aby uniknąć możliwego obejścia.

Praktyczne konsekwencje / ryzyko

Jeśli Twoja aplikacja używa vm2 do uruchamiania jakiegokolwiek kodu pochodzącego od użytkownika lub z nie w pełni zaufanego źródła, konsekwencje mogą obejmować:

  • przejęcie serwera/aplikacji (RCE),
  • kradzież sekretów (zmienne środowiskowe, tokeny CI/CD, klucze API),
  • pivot do sieci wewnętrznej,
  • modyfikację danych i łańcuchy ataków supply chain (np. modyfikacja artefaktów build).

Co istotne: wektor CVSS wskazuje m.in. AV:N oraz brak wymogu uprawnień i interakcji użytkownika (wg CNA/GitHub), co w praktyce oznacza, iż scenariusze zdalne są realne w wielu wdrożeniach.

Rekomendacje operacyjne / co zrobić teraz

  1. Zrób szybki inventory zależności
    • Sprawdź, czy vm2 jest zależnością bezpośrednią lub transytywną (np. npm ls vm2, SBOM, skan SCA).
  2. Zaktualizuj vm2 do wersji bezpiecznej
    • Minimum ≥ 3.10.2 (a najlepiej do najnowszej wersji w 3.10.x).
  3. Jeśli nie możesz zaktualizować „tu i teraz” – załóż, iż sandbox jest zawodny
    • Uruchamiaj niezaufany kod w oddzielnym procesie/serwisie z twardą izolacją (kontener/VM), bez dostępu do sekretów i z minimalnymi uprawnieniami.
    • Ogranicz egress (firewall), włącz profile typu AppArmor/SELinux/seccomp tam, gdzie to możliwe.
  4. Wdróż detekcję i kontrolę ryzyka
    • Monitoruj anomalie procesów (uruchomienia node, sh, bash, child_process), nietypowe połączenia sieciowe, zmiany plików.
  5. Rozważ alternatywę architektoniczną
    • Jeśli Twoim wymaganiem jest uruchamianie niezaufanego kodu, traktuj vm2 jako element wysokiego ryzyka i preferuj podejścia „defense-in-depth” (izolacja na poziomie OS, osobny worker pool, sandboxing poza jednym procesem Node). Kontekst „wracających ucieczek” w vm2 jest dobrze udokumentowany.

Różnice / porównania z innymi przypadkami

  • CVE-2026-22709 dotyczy wprost Promises i sanitizacji callbacków (then/catch) oraz różnicy między promise „lokalnym” a „globalnym” w kontekście async.
  • Wcześniejsze głośne podatności (np. CVE-2023-29017, CVE-2023-30547) również prowadziły do sandbox escape, ale wynikały z innych mechanizmów (np. obsługa wyjątków / sanitizacja wyjątków).

Wniosek praktyczny: choćby jeżeli „załataliście” jedną klasę bypassu, model zagrożeń dla vm2 powinien zakładać kolejne obejścia, dlatego izolacja warstwowa (process/container/VM) jest kluczowa.

Podsumowanie / najważniejsze wnioski

  • CVE-2026-22709 to krytyczny sandbox escape w vm2, umożliwiający RCE na hoście.
  • Podatne są wersje przed 3.10.2; fix został domknięty w 3.10.2.
  • Jeśli vm2 obsługuje kod użytkownika lub dane, które mogą zostać „przemycone” do wykonywanego JS, priorytetem jest natychmiastowy upgrade i izolacja defense-in-depth.

Źródła / bibliografia

  1. BleepingComputer – opis podatności, kontekst popularności i historia vm2 (BleepingComputer)
  2. NVD (NIST) – rekord CVE-2026-22709 i opis mechanizmu podatności (NVD)
  3. GitHub Advisory Database – GHSA-99p7-6v5w-7xg8, metryki i techniczne detale/PoC (GitHub)
  4. Semgrep Blog – omówienie ryzyka i rekomendacja aktualizacji do 3.10.2 (semgrep.dev)
  5. Snyk Vulnerability Database – widok wersji i statusu podatności w najnowszych wydaniach (VulnInfo Guide)
Idź do oryginalnego materiału