Brotli CVE-2026-111497: łatka dla Node.js, Bun i Pythona

Brotli CVE-2026-111497: łatka dla Node.js, Bun i Pythona

Brotli CVE-2026-111497: łatka dla Node.js, Bun i Pythona

CVE-2026-111497 to błąd uszkodzenia pamięci w dekoderze Brotli od Google, czyli kodzie w C, który rozpakowuje dane Content-Encoding: br. Spreparowane skompresowane dane zapisują poza końcem bufora, co może wywrócić program, ujawnić zawartość pamięci albo uruchomić kod atakującego. Node.js, Bun, pakiety Pythona Brotli i brotlicffi oraz Envoy mają każdy własną kopię tego dekodera, więc każdy trzeba zaktualizować osobno. Ten poradnik pokazuje, kiedy aplikacja jest naprawdę narażona, jak sprawdzić serwer jednym poleceniem i jak wdrożyć poprawkę, nie pomijając żadnego kontenera.

Jak poważna jest luka

  • Google ocenia ją na 9.2 (critical) w CVSS 4.0, Node.js jako high, Red Hat na 8.1.
  • Badacze z Imperva uruchomili własny kod na niezałatanym Node.js 24.22.0 na Linux ARM64, zarówno przez odpowiedź pobraną przez fetch, jak i przez treść żądania w Express. Exploit nie jest publiczny.
  • Ocena CISA z 23 października nie odnotowała wykorzystania luki w realnych atakach i nie ma wiarygodnego publicznego proof of concept.
  • Luka działa w obie strony: serwer, który rozpakowuje skompresowane dane wejściowe, może zostać zaatakowany przez klienta, a klient, który rozpakowuje skompresowane odpowiedzi, przez serwer.

Poprawka trafiła do kodu źródłowego Brotli 27 lutego, ale żadne wydanie Brotli nie zawierało jej aż do 21 października, dlatego wszystkie załatane runtime'y pojawiły się w tym samym tygodniu.

Czy jesteś narażony?

Zagrożony jest tylko kod, który dekoduje dane Brotli kontrolowane przez kogoś innego:

  • Node.js i Bun - wbudowany fetch() czytający odpowiedź wysłaną z Content-Encoding: br, wywołania Brotli z node:zlib na niezaufanych danych oraz parsery treści żądań, które rozpakowują przesyłane pliki w Brotli (Express 5, body-parser 2). Zwykły serwer HTTP w Node.js sam nie dekoduje treści żądań.
  • Python - wystarczy, że zainstalowany jest pakiet Brotli lub brotlicffi: requests, urllib3, httpx i aiohttp same dekodują wtedy odpowiedzi Brotli, nawet jeśli Twój kod nigdy nie importuje Brotli.
  • Envoy i Istio - tylko jeśli skonfigurowano filtr dekompresji Brotli.

Każda usługa, która wywołuje zewnętrzne API, webhooki, operatorów płatności albo scrapuje strony, wykonuje fetch() do serwerów, których nie kontrolujesz. Usunięcie br z Accept-Encoding nie jest poprawką: serwer i tak może wysłać Brotli.

Oprogramowanie Podatne Poprawione w
Node.js 22.x, 24.x, 26.x przed poprawką; 20.x i starsze (koniec wsparcia) 22.23.4, 24.22.1, 26.12.1
Bun 1.4.3 i starsze 1.4.4
Python Brotli 1.2.0 i starsze 1.2.1
Python brotlicffi 1.2.0.x i starsze 1.2.1.0
Google Brotli (biblioteka C) 1.0.3 - 1.2.0 1.0.10, 1.1.1, 1.2.1
Envoy 1.39.2, 1.38.5, 1.37.7, 1.36.11 1.40.0, 1.39.3, 1.38.6, 1.37.8, 1.36.12
Istio 1.31.0 - 1.31.1, 1.30.0 - 1.30.5, 1.29.0 - 1.29.8 1.31.2, 1.30.6, 1.29.9

Sprawdź serwer jednym poleceniem

Ten skrypt powłoki POSIX sprawdza Bun, Node.js i Pythona na maszynie (lub w kontenerze) i podaje, które są starsze niż poprawka. Zapisz go jako brotli-check.sh:

#!/bin/sh
# CVE-2026-111497 (Brotli decoder): which runtimes on this host are older than the fixes?
ver_lt() { [ "$1" = "$2" ] && return 1; [ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | head -n1)" = "$1" ]; }
if command -v bun >/dev/null 2>&1; then
  v=$(bun --version)
  if ver_lt "$v" 1.4.4; then echo "bun $v: VULNERABLE, upgrade to 1.4.4+"; else echo "bun $v: fixed"; fi
fi
if command -v node >/dev/null 2>&1; then
  v=$(node -p "process.versions.bun ? '' : process.versions.node")
  if [ -z "$v" ]; then echo "node: this is Bun's node shim, see the bun line"; else major=${v%%.*}
  case $major in
    22) fix=22.23.4 ;; 24) fix=24.22.1 ;; 26) fix=26.12.1 ;;
    *) fix= ;;
  esac
  if [ -z "$fix" ]; then echo "node $v: no fixed release for this line, move to 22, 24 or 26"
  elif ver_lt "$v" "$fix"; then echo "node $v: VULNERABLE, upgrade to $fix+"
  else echo "node $v: fixed"; fi
  fi
fi
for py in python3 python; do
  command -v $py >/dev/null 2>&1 || continue
  $py - <<'PY'
from importlib import metadata
for pkg, fix in (("Brotli", "1.2.1"), ("brotlicffi", "1.2.1.0")):
    try:
        v = metadata.version(pkg)
    except metadata.PackageNotFoundError:
        print(f"python {pkg}: not installed")
        continue
    a = [int(x) for x in v.split(".") if x.isdigit()]
    b = [int(x) for x in fix.split(".")]
    print(f"python {pkg} {v}: {'VULNERABLE, upgrade to ' + fix + '+' if a < b else 'fixed'}")
PY
  break
done
sh brotli-check.sh
docker exec my-app sh -s < brotli-check.sh   # the same check inside a running container

Wynik sprawdzony 2026-10-24 (laptop programisty, potem oficjalne obrazy Dockera):

bun 1.4.1: VULNERABLE, upgrade to 1.4.4+
node 26.6.0: VULNERABLE, upgrade to 26.12.1+
python Brotli: not installed
python brotlicffi: not installed
bun 1.4.4: fixed
node: this is Bun's node shim, see the bun line
node 22.23.4: fixed
node 16.20.2: no fixed release for this line, move to 22, 24 or 26
python Brotli 1.1.0: VULNERABLE, upgrade to 1.2.1+
python brotlicffi: not installed

Uruchom go w każdym kontenerze, nie tylko na hoście: Node.js na hoście nic nie mówi o tym, który jest wbudowany w obraz.

Jak wdrożyć poprawkę

  1. Znajdź każdą kopię. Najczęściej pomijane są obrazy. Wypisz, co działa: docker ps --format '{{.Image}}', potem linie FROM w Twoich Dockerfile. Tag taki jak node:22 czy oven/bun:alpine przesuwa się do przodu tylko wtedy, gdy zrobisz pull; przypięty tag, np. oven/bun:1.4.1-slim, nie przesuwa się nigdy.
  2. Zaktualizuj runtime. Podbij przypięte tagi (oven/bun:1.4.4-slim, node:22.23.4-alpine), na hostach wykonaj bun upgrade i zaktualizuj pakiety Node.js, a w środowiskach Pythona pip install -U "Brotli>=1.2.1" (lub brotlicffi>=1.2.1.0). Jeśli aplikacja w Pythonie nie potrzebuje Brotli, pip uninstall Brotli brotlicffi również zamyka tę drogę: klienty HTTP przechodzą wtedy na gzip i deflate.
  3. Przebuduj i podmień. docker compose build --pull && docker compose up -d. Działający proces trzyma stary dekoder aż do restartu, więc zrestartuj też usługi na hostach.
  4. Zweryfikuj. Uruchom skrypt ponownie w każdym kontenerze (docker exec <name> bun --version to szybka wersja). Lockfile z --frozen-lockfile mogą wywrócić przebudowę po podbiciu zależności: commituj zaktualizowany lockfile razem z package.json.
  5. Nie możesz jeszcze zaktualizować? Odrzucaj na proxy żądania z Content-Encoding: br, zanim cokolwiek zdekoduje treść, i unikaj pobierania danych z niezaufanych hostów. Vercel zaznacza, że reguły firewalla nie obejmują odpowiedzi, które Twój własny kod pobiera z innych serwerów - pomaga tylko aktualizacja.

Dla stosu Node.js na VM zobacz Serwer cloud dla Node.js, dla Pythona Serwer cloud dla Pythona i Flaska, a dla obrazów, które czysto się przebudowują, Serwer cloud dla Docker Swarm.

Co zrobiliśmy

W ciągu kilku dni od wydania poprawek przenieśliśmy każdą usługę DCXV działającą na Bun na 1.4.4: przypięte obrazy bazowe dostały poprawione tagi, a wszystkie obrazy zostały przebudowane ze świeżym pull. Nasze komponenty Node.js nie dekodują treści Brotli, a nasze proxy nie mają dekompresji Brotli. Serwerami klientów zarządzają ich właściciele: jeśli uruchamiasz Node.js, Bun lub Pythona na serwerze cloud DCXV, wykonaj powyższe sprawdzenie jeszcze dziś albo zapytaj nas o zarządzaną administrację serwerem.

Źródła (sprawdzone 2026-10-24): październikowe wydania bezpieczeństwa Node.js 2026 (22.23.4, 24.22.1, 26.12.1), wydanie Bun 1.4.4, ocena CISA z 23 października 2026 i badania Imperva.

PHP2Shell: sprawdź i załataj luki RCE w PHP na serwerze
clouddedicatedhosting

PHP2Shell: sprawdź i załataj luki RCE w PHP na serwerze

PHP2Shell (CVE-2026-109618, CVE-2026-109619) pozwala żądaniu bez logowania wykonać kod w PHP. Poprawione wersje, sprawdzony skrypt, obejścia w php.ini i plan aktualizacji.

Brotli CVE-2026-111497: łatka dla Node.js, Bun i Pythona
cloudnetworkinginfrastructure

Brotli CVE-2026-111497: łatka dla Node.js, Bun i Pythona

Luka w dekoderze Brotli (CVE-2026-111497) pozwala uruchomić kod przez fetch() w Node.js i Bun lub klienty HTTP Pythona. Wersje z poprawką, skrypt testowy i przebudowa.

Jak dobrać serwer cloud do SaaS: CPU, RAM, NVMe i backupy
cloudinfrastructurepricing

Jak dobrać serwer cloud do SaaS: CPU, RAM, NVMe i backupy

Dobierz serwer cloud do SaaS w Dockerze i Node.js: budżet pamięci, limity CPU, NVMe i backupy, test obciążeniowy k6, pełna cena miesięczna i arkusz doboru.

Agenty AI do kodu na VPS w UE: utwardzona konfiguracja
aicloudhosting

Agenty AI do kodu na VPS w UE: utwardzona konfiguracja

Uruchom agentów AI do kodu na VPS w UE z ograniczeniami: jednorazowe katalogi, lista dozwolonego ruchu, tokeny, limity, sprawdzony kod, ryzyka i koszt serwera.

Geolokalizacja IPv4 po transferze: jak poprawić kraj
ipv4networkingtransfer

Geolokalizacja IPv4 po transferze: jak poprawić kraj

Przeniesiony blok IPv4 nadal pokazuje poprzedni kraj? Sprawdź WHOIS, BGP i GeoIP, opublikuj geofeed i poproś dostawców o poprawki bez obietnic terminów.