CVE-2026-111497: falla nel decoder Brotli riguarda Node.js, Bun, Python, .NET ed Envoy: cosa aggiornare ora
Un errore nel decoder Brotli di Google (versioni da 1.0.3 a 1.2.0) consente, tramite dati appositamente predisposti, una scrittura out-of-bounds fino all'esecuzione di codice (CVE-2026-111497, CVSS 9.2). È interessato qualsiasi software che decomprime dati Brotli provenienti da fonti esterne: Node.js, Bun, Python con Brotli/brotlicffi, .NET, Envoy, curl. Sono disponibili aggiornamenti.
Il decoder Brotli di Google contiene, nelle versioni da 1.0.3 a 1.2.0, un errore che consente a dati Brotli appositamente predisposti di sovrascrivere memoria al di fuori di un buffer. La vulnerabilità ha l’identificativo CVE-2026-111497 e una valutazione di 9.2 secondo CVSS 4.0; pubblicamente è nota con i nomi Node2Shell e Broccoli2Shell. Le possibili conseguenze sono un arresto anomalo, la lettura della memoria del processo o l’esecuzione di codice. Imperva ha dimostrato l’esecuzione di codice su un Node.js 24.22.0 non modificato. Il codice proof-of-concept è in parte pubblico, ma finora non sono noti attacchi in corso. Node.js ha pubblicato le correzioni il 21 ottobre 2026, mentre gli altri ecosistemi hanno seguito entro il 26 ottobre.
Dopo la segnalazione ho verificato i miei sistemi: il build runner di questo sito utilizzava ancora Node.js 22.23.1, nonostante la versione 22.23.4 fosse disponibile da giorni. Il motivo è illustrato nella sezione dedicata a GitHub Actions più avanti; riguarda ogni runner self-hosted con actions/setup-node.
Supporto per inventario e aggiornamenti
Se avete bisogno di aiuto per individuare componenti interessati in applicazioni, immagini container o pipeline CI, utilizzate il modulo di contatto su adeptio.ch. Rispondo anche con breve preavviso.
Causa
L’errore si trova nella funzione DecodeBlockTypeAndLength(). Elabora i cambi di blocco nel flusso di dati compresso, ovvero i punti in cui il decoder passa a un altro codice Huffman. Nelle versioni vulnerabili, la funzione restituisce solo un valore booleano; BROTLI_FALSE significa sia “flusso di dati non valido” sia “necessario altro input”. Un flusso di dati predisposto dichiara un unico tipo di blocco ed esaurisce la sua lunghezza, forzando così un cambio che non può riuscire. Il decoder lo interpreta come input mancante, aggiunge altri byte a un buffer interno di 8 byte e scrive oltre il suo limite.
La correzione upstream (commit 0ed4268 nel repository google/brotli) introduce un proprio codice di errore BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH e interrompe la decodifica. OpenAI Codex Security aveva già segnalato l’errore nel febbraio 2026. All’epoca la correzione era finita nel codice sorgente, ma non era stata classificata come correzione di sicurezza e non è apparsa in alcuna release. È stata distribuita solo con Brotli 1.2.1 e le release Node.js del 21 ottobre 2026.
Quando un sistema è attaccabile
Comprimere con Brotli è innocuo; è attaccabile solo chi decomprime dati Brotli provenienti da una fonte esterna. Ci sono due direzioni:
- Client: L’applicazione richiama un URL e decodifica una risposta con
Content-Encoding: br. Ilfetch()integrato di Node.js e Bun lo fa automaticamente e non può essere disattivato. Sono quindi interessati crawler, ricevitori di webhook con callback, anteprime di link, script di monitoraggio e qualsiasi automazione che carichi contenuti da server di terzi. A tale scopo, a un attaccante basta controllare uno dei server richiamati. - Server: Un framework o un middleware decomprime request body con
Content-Encoding: br. Imperva cita per Node.jsbody-parser2.0.0 fino a 2.3.0 ed Express 5.0.0 fino a 5.3.0 con parser configuratijson()oraw(). Un serverhttpnativo di Node.js non decodifica autonomamente i body in ingresso.
Apache mod_brotli e i diffusi moduli Brotli per nginx comprimono soltanto e pertanto non sono interessati. Envoy e Istio sono vulnerabili solo se è configurato il filtro Brotli Decompressor; Istio non lo attiva per impostazione predefinita.
Componenti interessati e versioni corrette
| Componente | Versioni corrette | Nota |
|---|---|---|
| libbrotli (Google Brotli) | 1.2.1, 1.1.1, 1.0.10 | sono interessate le versioni da 1.0.3 a 1.2.0 |
| Node.js | 26.12.1, 24.22.1, 22.23.4 | Release del 21.10.2026, contiene ulteriori correzioni (DNS, verifica del nome TLS) |
| Bun | 1.4.4 | ricompilare gli eseguibili creati con bun build --compile |
Python Brotli | 1.2.1 | utilizzato automaticamente da urllib3, requests e aiohttp se installato |
Python brotlicffi | 1.2.1.0 | ugualmente; anche come extra httpx[brotli] |
| .NET | 8.0.33, 9.0.22, 10.0.14, 11 RC3 | aggiornamento out-of-band del 25.10.2026; .NET Framework non interessato, .NET 7 senza correzione |
| Envoy | 1.40.0, 1.39.3, 1.38.6, 1.37.8 | solo con filtro Brotli Decompressor |
| Istio | 1.31.2, 1.30.6, 1.29.9 | solo con Brotli Decompressor in un EnvoyFilter |
| Java brotli4j | 1.24.0 | il wrapper JNI include una propria copia di Brotli |
| curl/libcurl | build con Brotli 1.2.1 | solo con --compressed o CURLOPT_ACCEPT_ENCODING |
Ulteriori binding per PHP, Ruby e Go (cgo) dipendono dalla libbrotli di sistema o inclusa nel pacchetto. Tra le distribuzioni Linux, Debian 12 e 13, Alpine e Amazon Linux 2023 avevano pacchetti corretti al 26 ottobre; Fedora e Red Hat erano corretti solo in parte, mentre per Ubuntu e SUSE la correzione era ancora in attesa.
Individuare le versioni interessate
Per Node.js, Python e la libreria di sistema sono sufficienti tre interrogazioni. Su Windows, node -v restituisce lo stesso risultato che su Linux.
node -v
pip show Brotli brotlicffi
pipdeptree -r -p Brotli
Su Debian/Ubuntu e Alpine, il gestore dei pacchetti mostra la versione della libreria di sistema:
dpkg -l 'libbrotli*'
apk info -v brotli-libs
Le immagini container devono essere verificate separatamente: un host aggiornato non serve a nulla se l’immagine contiene una vecchia versione di Node.js o una libbrotli inclusa nel pacchetto. Dopo l’aggiornamento, le immagini devono essere ricompilate e i workload in esecuzione riavviati; per Bun e brotli4j questo vale anche per le applicazioni che integrano Brotli staticamente.
Runner GitHub self-hosted: setup-node prende la versione dalla cache
actions/setup-node con node-version: 22 non verifica per impostazione predefinita se esiste una versione 22 più recente. Se nella cache degli strumenti del runner è già presente una versione adatta, viene usata quella. Sui runner ospitati da GitHub, l’immagine viene distribuita nuovamente con regolarità; un runner self-hosted, invece, conserva la cache finché qualcuno non la svuota. Nel log compare quindi, ad esempio, Found in cache @ .../_tool/node/22.23.1/x64.
Una riga aggiuntiva in ogni passaggio setup-node risolve il problema:
- uses: actions/setup-node@v4
with:
node-version: 22
check-latest: true
In alternativa, si può indicare in modo fisso la versione minima (node-version: 22.23.4); occorre però aggiornarla a ogni release di sicurezza. Questo è particolarmente rilevante per pipeline che richiamano contenuti da server esterni, come scanner, verificatori di link o feed: in questi casi fetch() comunica con server che non controllate e il runner di norma ha accesso ai secret di deployment.
Se non è subito possibile aggiornare
Le mitigazioni intervengono sulla decodifica:
- In ingresso: rifiutare al reverse proxy o nel middleware le richieste con
Content-Encodingcontenentebr. Il confronto deve ignorare maiuscole e minuscole e rilevare anche elenchi comegzip, br. - In uscita: rimuovere
brdaAccept-Encodinge scartare le risposte conContent-Encoding: brprima della decodifica. La sola rimozione daAccept-Encodingnon è sufficiente, perché un server predisposto può comunque inviare la codifica. Con ilfetch()integrato di Node.js e Bun non è possibile; in quel caso aiuta solo l’aggiornamento. - curl: omettere
--compressed; in libcurl mantenereCURLOPT_ACCEPT_ENCODINGsuNULL. - Python: disinstallare
Brotliebrotlicffi, quindi rimuovere dalle dipendenze extra comehttpx[brotli]. urllib3, requests e aiohttp ricadranno quindi su gzip e deflate. - Envoy/Istio: rimuovere il Brotli Decompressor dalla configurazione o dagli EnvoyFilter e controllare la configurazione in esecuzione.
Cloudflare Workers e browser
Chi esegue applicazioni come Cloudflare Worker non gestisce un proprio processo Node.js; la runtime workerd è gestita e aggiornata da Cloudflare. Al 26 ottobre non era disponibile una dichiarazione di Cloudflare su CVE-2026-111497 e i clienti non possono modificare nulla nella runtime stessa. Restano però interessati gli strumenti attorno al Worker: script di build, wrangler e ambienti di sviluppo locali vengono eseguiti su Node.js e dovrebbero usare una versione corretta. I browser usano implementazioni Brotli proprie; nelle comunicazioni dei produttori e dei ricercatori di sicurezza non sono indicati come interessati.
Cronologia
| Data | Evento |
|---|---|
| Febbraio 2026 | OpenAI Codex Security segnala l’errore; la correzione finisce nel codice sorgente di Brotli senza release |
| 21.10.2026 | Node.js pubblica 26.12.1, 24.22.1 e 22.23.4 |
| 22.10.2026 | Brotli 1.2.1 e brotlicffi 1.2.1.0 su PyPI; analisi di Imperva con esecuzione di codice |
| 23.10.2026 | Correzioni per libbrotli, Bun, Envoy e Istio |
| 24.10.2026 | brotli4j 1.24.0, pacchetti per Amazon Linux 2023 |
| 25.10.2026 | Aggiornamenti out-of-band per .NET |
| 26.10.2026 | Debian e Alpine corretti, Fedora e Red Hat parzialmente |
Commenti
I commenti vengono caricati da GitHub / Giscus.