Un singur bug în Brotli, multe produse afectate: CVE-2026-111497 ajunge la Node.js, Bun, Python și Envoy
O vulnerabilitate de siguranță a memoriei din biblioteca de referință pentru decompresia Brotli s-a transformat într-un exercițiu de patching care traversează mai multe ecosisteme. Identificată ca CVE-2026-111497, ea permite ca date comprimate Brotli special construite să scrie dincolo de capătul unui buffer. Pentru că același decodor este integrat în runtime-uri, proxy-uri și biblioteci Python, corecția trebuie aplicată produs cu produs — iar unele dintre ele abia acum recuperează.
Ce s-a întâmplat
Versiuni corectate de Node.js și o bibliotecă Brotli actualizată au apărut pe 21 octombrie 2026, iar corecțiile pentru celelalte produse afectate au urmat în zilele de după. Modificarea care închide breșa a intrat, de fapt, în codul sursă Brotli încă din februarie, dar atunci nimeni nu a recunoscut-o drept o corecție de securitate și nicio versiune Brotli nu a inclus-o până în octombrie — așa că proiectele dependente au continuat luni de zile să livreze decodorul vulnerabil.
Un payload malițios poate corupe memoria și poate provoca un crash, o scurgere de memorie sau, în cel mai rău caz, executarea de cod controlat de atacator. Execuția de cod la distanță a fost demonstrată pe o singură versiune nepatch-uită — Node.js 24.22.0 pentru Linux pe ARM64 — atât printr-un răspuns preluat cu fetch, cât și printr-un corp de cerere încărcat. Au fost necesare mai multe încercări, exploit-ul nu a fost publicat, iar execuția de cod nu a fost demonstrată pe celelalte produse afectate. Nu a fost raportată nicio exploatare activă, și nu există un proof-of-concept public fiabil.
Severitatea diferă în funcție de cine o evaluează: CVE-ul are un scor critic de 9,2 pe CVSS 4.0, în timp ce unii furnizori îl clasifică drept ridicat sau important (în jur de 8,1).
Cine este afectat
| Software | Vulnerabil | Corectat | Expus când |
|---|---|---|---|
| Node.js | versiunile anterioare actualizării de securitate din 21 octombrie | versiunile de securitate din 21 octombrie | fetch() citește un răspuns br sau un body parser despachetează un upload Brotli |
| Bun | 1.4.3 și mai vechi | 1.4.4 | fetch() citește un răspuns br sau codul folosește node:zlib |
| Envoy | până la 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 | decompresorul Brotli este configurat |
| 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 | decompresia Brotli este activată |
Python Brotli | 1.2.0 și mai vechi | 1.2.1 | instalat, iar un client HTTP decodează br |
Python brotlicffi | 1.2.0.x și mai vechi | 1.2.1.0 | instalat, iar un client HTTP decodează br |
| cdxgen | binare/imagini standalone 13.4.0, 12.8.8 și mai vechi | 13.5.0, 12.8.9 | scanează input neverificat |
De ce contează
Întrebarea decisivă este simplă: software-ul tău decodează date Brotli controlate de altcineva?
- Node.js și Bun sunt expuse când
fetch()-ul integrat primește un răspuns trimis cuContent-Encoding: brsau când un middleware pentru corpul cererii — de exemplu Express 5 cu body-parser 2 — despachetează un upload Brotli. Un server HTTP Node.js simplu nu decodează singur corpul cererilor. - Envoy și Istio pot fi atinse doar când decompresia Brotli este activată, de exemplu printr-un filtru Envoy. Dacă este dezactivată, bug-ul nu poate fi declanșat.
- Python este cazul înșelător. Simpla instalare a pachetelor
Brotlisaubrotlicffieste suficientă: clienți HTTP populari precum requests, urllib3, httpx și aiohttp le folosesc automat și decodează singuri răspunsurile Brotli. O aplicație poate fi expusă fără să importe vreodată Brotli în propriul cod.
Vulnerabilitatea funcționează în ambele direcții. Un server nepatch-uit care acceptă input comprimat ar putea fi preluat de un client malițios, iar un client nepatch-uit care acceptă răspunsuri comprimate ar putea fi preluat de un server malițios. Un web application firewall poate filtra traficul de intrare, dar nu protejează răspunsurile pe care propriul cod le preia de la alte servere — pe acea cale, doar actualizarea închide breșa.
Două zone oarbe complică urmărirea. Înregistrarea CVE indică depozitul Brotli original, nu pachetele PyPI, așa că scanerele de dependențe care se bazează pe datele de advisory GitHub s-ar putea să nu semnaleze încă bibliotecile Python; intrările dedicate (PYSEC-2026-4322 și PYSEC-2026-4323) au fost adăugate abia pe 23 octombrie. Iar pachetele de sistem avansează în ritmuri diferite: Debian 13 (trixie) a livrat un pachet brotli corectat (1.1.0-2+deb13u1) pe 23 octombrie, în timp ce Amazon Linux 2023 încă lista pachetele brotli și Node.js 24 ca așteptând o corecție la data de 22 octombrie.
Ce trebuie făcut
- Actualizează la o versiune corectată din tabelul de mai sus, apoi repornește serviciile și reconstruiește imaginile de container — un proces care rulează păstrează vechiul decodor în memorie până la repornire.
- Dacă nu poți actualiza încă, oprește decodarea Brotli din surse nesigure:
- respinge cererile care sosesc cu
Content-Encoding: brînainte ca vreun proxy sau parser să decodeze corpul; - dezactivează decodarea automată Brotli în clienții HTTP și respinge răspunsurile Brotli înainte de a fi decodate;
- în Python, dezinstalează
Brotlișibrotlicffi, astfel încât clienții să revină la gzip și deflate.
- respinge cererile care sosesc cu
- Nu te baza doar pe
Accept-Encoding. Eliminareabrdin acest header nu este, singură, o apărare — un server ostil poate trimite Brotli indiferent ce cere clientul. Pentru Node.js nu există o soluție temporară publicată: actualizarea runtime-ului este remedierea. - Verifică manual, nu doar cu scanerul. Rulează
pip show brotli brotlicffiîn toate mediile și imaginile Python și urmărește pachetele brotli și Node.js ale distribuției tale până când sunt corectate.
Astfel de bug-uri se ascund în dependențe opționale și tranzitive pe care nimeni nu le-a ales intenționat. Code review-ul asistat de AI al echipei noastre inventariază ce încarcă de fapt aplicațiile tale — inclusiv bibliotecile pe care clienții HTTP le folosesc în tăcere — și le compară cu avertismentele de securitate curente, astfel încât un decodor vulnerabil să nu rămână invizibil doar pentru că nu este importat direct în codul tău.
