21 października 2026 r. projekt Node.js opublikował wydania 22.23.4, 24.22.1 i 26.12.1. Naprawiają one dziesięć podatności, z których cztery mają wysoką ocenę. Najpoważniejsza z nich, CVE-2026-111497, to zapis poza granicami bufora w dekoderze Brotli w Node: spreparowane skompresowane dane mogą uszkodzić pamięć, a firma hostingowa Vercel informuje, że badacze wykorzystali ten błąd do odczytu pamięci procesu i uruchamiania poleceń z uprawnieniami procesu Node.js. Dwa kolejne błędy o wysokiej ważności sprawiają, że certyfikat TLS przechodzi weryfikację nazwy hosta, choć nie powinien. Node.js 20 i 25 osiągnęły koniec wsparcia i nie otrzymają poprawki.
Które wersje zostały poprawione
| Gałąź wydań | Poprawione w | Status |
|---|---|---|
| 26.x | 26.12.1 | bieżąca |
| 24.x (LTS) | 24.22.1 | wspierana |
| 22.x (LTS) | 22.23.4 | wspierana |
| 25.x | brak poprawki | koniec wsparcia, należy przejść na 26 lub 24 |
| 20.x | brak poprawki | koniec wsparcia od 30 kwietnia 2026 r., należy przejść na 22 lub 24 |
Jakie to dziesięć błędów
| CVE | Ważność | Problem | Gałęzie |
|---|---|---|---|
| CVE-2026-111497 | Wysoka | Zapis poza granicami bufora w dekoderze Brotli, może prowadzić do wykonania kodu | 26, 24, 22 |
| CVE-2026-105483 | Wysoka | Weryfikacja nazwy hosta TLS przechodzi, gdy adres IP jest zapisany cyframi pełnej szerokości | 26, 24 |
| CVE-2026-106069 | Wysoka | Weryfikacja nazwy hosta TLS przechodzi, gdy host zostaje luźno zinterpretowany jako adres IP | 26, 24, 22 |
| CVE-2026-105482 | Wysoka | dns.resolve ucina nazwy na znaku NUL | 26, 24, 22 |
| CVE-2026-105481 | Średnia | Gniazdo keep-alive może przyjąć odpowiedź zapisaną przed wysłaniem żądania | 26, 24, 22 |
| CVE-2026-106072 | Średnia | Nazwa DNS w certyfikacie może uwierzytelnić punkt końcowy IP dla hostów IPv4 w formie niekanonicznej | 26, 24, 22 |
| CVE-2026-106074 | Średnia | randomUUID() i randomInt() powtarzają te same wartości w migawkach uruchomieniowych i aplikacjach typu single executable | 26, 24, 22 |
| CVE-2026-106073 | Niska | Obejście Permission Model przez fs.realpathSync | 26, 24, 22 |
| CVE-2026-106070 | Niska | ZipFile zwraca bajty kontrolowane przez atakującego po nieudanej weryfikacji nagłówka | 26 |
| CVE-2026-106071 | Niska | Permission Model przyznaje zbyt szeroki dostęp do plików przez symbole wieloznaczne | 26 |
Wydania aktualizują także dołączone komponenty: c-ares, Undici, listę zaufanych urzędów certyfikacji (usunięto z niej skompromitowany pośredni urząd certyfikacji eMudhra), OpenSSL w gałęziach 24 i 22 oraz SQLite w gałęzi 22.
Kto jest narażony na błąd w Brotli
Node.js sam z siebie nie dekoduje Brotli. Są Państwo narażeni, gdy Państwa kod lub używana przez niego biblioteka dekompresuje dane Brotli, które kontroluje ktoś inny. Zdarza się to częściej, niż się wydaje:
- Wbudowane
fetch()automatycznie dekoduje odpowiedzi zContent-Encoding: br. Usługa, która pobiera adresy URL wskazane przez użytkowników, webhooki lub zewnętrzne API, może otrzymać złośliwą odpowiedź. - axios, got i node-fetch również domyślnie dekodują skompresowane odpowiedzi.
- Express 5 (body-parser 2) domyślnie dekoduje treści żądań skompresowane Brotli, więc API może otrzymać dane bezpośrednio od atakującego.
- Każde wywołanie
zlib.brotliDecompress,zlib.createBrotliDecompresslubDecompressionStreamna przesłanych plikach albo danych od stron trzecich.
Poprawki należy wdrożyć najpierw tam, gdzie te elementy mają kontakt z internetem: w publicznych API przyjmujących skompresowane treści, w usługach pobierających adresy URL podane przez użytkowników oraz wszędzie tam, gdzie rozpakowywane są przesłane pliki.
Błędy TLS mają znaczenie głównie wtedy, gdy atakujący może uzyskać od zaufanego przez Państwa klienta urzędu certyfikacji certyfikat zawierający nazwę DNS o kształcie adresu IP, a błąd DNS wtedy, gdy Państwa kod przekazuje do dns.resolve dane z zewnątrz. Według commita z poprawką błędy TLS nie są łatwe do wykorzystania, ale ta sama aktualizacja je zamyka.
Krok 1: odszukanie każdego środowiska Node.js
W Linuksie należy wypisać każdy plik binarny node wraz z wersją:
sudo find / -xdev -type f -name node -perm -u+x 2>/dev/null | while read -r n; do echo "$n: $("$n" --version 2>/dev/null)"; done
Trzeba sprawdzić, z jakiego środowiska korzystają działające procesy:
for p in $(pgrep -x node); do echo "$p $(sudo readlink -f /proc/$p/exe)"; done
W Dockerze należy sprawdzić każdy działający kontener:
for c in $(docker ps --format '{{.Names}}'); do echo "$c: $(docker exec "$c" node --version 2>/dev/null)"; done
Warto też sprawdzić menedżery wersji (nvm, fnm, Volta, asdf), runnery CI, obrazy buildów, aplikacje Electron i funkcje serverless, w których wersja środowiska jest ustawiona w konfiguracji projektu.
Krok 2: aktualizacja
Ubuntu i Debian z pakietami NodeSource:
sudo apt update && sudo apt install --only-upgrade nodejs && node --version
Z nvm:
nvm install 24.22.1 && nvm alias default 24.22.1
Kontenery: należy zmienić obraz bazowy na stałą wersję, na przykład node:24.22.1-alpine lub node:22.23.4-bookworm-slim, przebudować obraz i wdrożyć go ponownie. Aktualizacja hosta nie zmienia tego, co działa wewnątrz kontenera.
Platformy serverless i hostingowe: na Vercel projekty na 22.x i 24.x są łatane przez Vercel, a Vercel dodał reguły zapory przeciw atakowi przychodzącemu; projekty nadal działające na 20.x muszą przejść na 22.x lub 24.x i zostać wdrożone ponownie. Na innych platformach należy sprawdzić komunikat dostawcy i wdrożyć ponownie, gdy poprawione środowisko będzie dostępne.
Pakiety dystrybucji, takie jak własny pakiet nodejs w Ubuntu, często pozostają w tyle. Jeśli node --version nie pokazuje 22.23.4, 24.22.1 ani 26.12.1 (ani kompilacji dystrybucji, która wymienia te CVE), należy użyć oficjalnych wydań.
Krok 3: ponowne uruchomienie i weryfikacja
Działający proces zachowuje stare środowisko do czasu ponownego uruchomienia. Po aktualizacji pakietu w Linuksie to polecenie wypisuje procesy node, które nadal korzystają z zastąpionego pliku binarnego:
sudo ls -l /proc/*/exe 2>/dev/null | grep -i 'node.*(deleted)'
Te usługi trzeba zrestartować (na przykład poleceniem systemctl restart, pm2 reload all albo nowym wdrożeniem) i ponownie uruchomić polecenia z kroku 1.
Gdy nie można zaktualizować dziś
Żadne z tych rozwiązań nie zastępuje aktualizacji, ale na kilka dni zmniejszają ryzyko:
- Należy odrzucać treści żądań skompresowane Brotli, zanim trafią do aplikacji, na przykład w NGINX za pomocą
if ($http_content_encoding ~* br) { return 415; }albo w middleware uruchamianym przed parserami treści. - Należy wyłączyć automatyczną dekompresję dla żądań do niezaufanych serwerów:
decompress: falsew axios i got,compress: falsew node-fetch alborequest()z undici, które niczego nie dekompresuje. Wbudowanegofetch()nie da się wyłączyć. - Pobieranie adresów URL podanych przez użytkowników należy uruchamiać w osobnym procesie z możliwie najmniejszymi uprawnieniami.
- Zanim dane z zewnątrz trafią do
dns.resolve, należy odrzucać nazwy zawierające znak NUL.
Jeśli nie mają Państwo pewności, które usługi dekodują niezaufane dane, albo potrzebują Państwo pomocy w aktualizacji systemu produkcyjnego bez przestoju, pomoże nasz zespół bezpiecznego oprogramowania oraz zespół zarządzanego bezpieczeństwa.
