Il 5 dicembre 2025 alle 08:47 UTC (tutti gli orari in questo blog sono espressi nel fuso orario UTC), una parte della rete di Cloudflare ha iniziato a riscontrare disservizi significativi. L'episodio è stato risolto alle 09:12 (con un impatto totale di circa 25 minuti), quando tutti i servizi sono stati completamente ripristinati.
Il disservizio ha riguardato una parte della nostra clientela, interessando circa il 28% di tutto il traffico HTTP gestito da Cloudflare. È importante notare che, affinché un singolo cliente fosse coinvolto, era necessaria una combinazione di diversi fattori specifici.
Il problema non è stato causato, direttamente o indirettamente, da un attacco informatico ai sistemi di Cloudflare o da attività dannose di alcun genere. È stato invece innescato da alcune modifiche che avevamo implementato nella nostra logica di analisi del corpo delle richieste. Queste modifiche erano state introdotte nel tentativo di rilevare e mitigare una vulnerabilità a livello di settore appena scoperta e divulgata questa settimana, relativa ai componenti del server React.
Siamo consapevoli che qualsiasi disservizio da noi causato sia inaccettabile e riconosciamo di aver nuovamente deluso le aspettative della community di Internet, specialmente dopo l'incidente del 18 novembre. La prossima settimana pubblicheremo un resoconto dettagliato sul lavoro che stiamo intraprendendo per evitare che eventi come questo possano ripetersi.
Il grafico seguente illustra l'andamento degli errori HTTP 500 serviti dalla nostra rete durante l'incidente (la linea rossa, in basso), in contrasto con il traffico totale di Cloudflare non interessato (la linea verde, in alto).
Il Web Application Firewall (WAF) di Cloudflare è progettato per proteggere i clienti da payload dannosi, intercettandoli e bloccandoli. Per eseguire questa analisi, il proxy di Cloudflare deve memorizzare temporaneamente il contenuto del corpo della richiesta HTTP in un buffer. In precedenza, la dimensione di questo buffer era fissata a 128 KB.
Nell'ambito del nostro sforzo costante per proteggere i clienti che utilizzano React da una vulnerabilità critica recentemente scoperta (identificata come CVE-2025-55182), abbiamo iniziato a implementare un aumento della dimensione del buffer fino a 1 MB. Questo limite è stato scelto perché è quello predefinito consentito dalle applicazioni Next.js. Il nostro obiettivo era massimizzare il numero di clienti che potevano beneficiare di questa protezione essenziale.
Questa prima modifica è stata implementata utilizzando il nostro sistema di distribuzione graduale. Durante l'implementazione, abbiamo notato che il nostro strumento di test WAF interno non supportava l'aumento delle dimensioni del buffer. Poiché questo strumento di test interno non era necessario in quel momento e non influiva sul traffico dei clienti, abbiamo apportato una seconda modifica per disattivarlo.
Questa seconda modifica, che ha comportato la disattivazione del nostro strumento di test WAF, è stata implementata utilizzando il nostro sistema di configurazione globale. Questo sistema non esegue implementazioni graduali, ma propaga le modifiche in pochi secondi all'intera flotta di server nella nostra rete ed è attualmente in fase di revisione a seguito del precedente episodio del 18 novembre.
Purtroppo, nella nostra versione FL1 del proxy, in determinate circostanze, la seconda modifica che prevedeva lo spegnimento del nostro strumento di test delle regole WAF ha causato uno stato di errore che ha causato la distribuzione di codici di errore HTTP 500 da parte della nostra rete.
Non appena questa modifica si è propagata alla rete globale, l'esecuzione del codice nel nostro proxy FL1 ha riscontrato un bug nel modulo delle regole, che ha generato la seguente eccezione Lua:
[lua] Failed to run module rulesets callback late_routing: /usr/local/nginx-fl/lua/modules/init.lua:314: attempt to index field 'execute' (a nil value)
il che ha causato l'emissione generalizzata di errori con codice HTTP 500.
Il problema è stato identificato poco dopo l'applicazione della modifica e il ripristino è stato eseguito rapidamente alle 09:12. Tutta la gestione del traffico è tornata alla normalità non appena è stata ristabilita la configurazione precedente.
I clienti interessati sono stati specificamente quelli le cui risorse web erano servite dalla nostra versione precedente del proxy, FL1, E che avevano distribuito Cloudflare Managed Ruleset. Tutte le richieste dirette ai siti web che rientravano in questa configurazione hanno restituito un errore HTTP 500, con l'unica piccola eccezione di alcuni endpoint di test come /cdn-cgi/trace.
I clienti non interessati includevano quelli a cui non era applicata la configurazione sopra descritta. Anche il traffico dei clienti servito dalla nostra China Network non ha subito ripercussioni.
Il sistema di regole di Cloudflare è costituito da set di regole che vengono applicati e valutati per ogni singola richiesta che elaboriamo. Ogni regola definisce due elementi: un filtro che seleziona una specifica porzione di traffico, e un'azione che applica un effetto a tale traffico. Le azioni più comuni sono "block", "log" o "skip". Esiste anche l'azione "execute", utilizzata per avviare la valutazione di un ulteriore set di regole.
Il nostro sistema di registrazione interno sfrutta proprio questa funzione per valutare nuove regole prima di renderle pubbliche. In pratica, un set di regole di livello superiore esegue un altro set contenente le regole di test. Erano precisamente queste regole di test che stavamo cercando di disabilitare.
Il nostro sistema di regole include un sottosistema killswitch integrato, progettato per disabilitare rapidamente qualsiasi regola che manifesti un comportamento anomalo. Questo killswitch riceve i comandi dal sistema di configurazione globale, citato in precedenza, ed è un meccanismo che abbiamo utilizzato in diverse occasioni passate per mitigare gli incidenti. Anche in questo caso, è stata seguita una procedura operativa standard ben definita.
Il punto critico è che non avevamo mai applicato il killswitch a una regola con azione "execute". Quando il killswitch è stato applicato, il codice ha funzionato come previsto, saltando la valutazione dell'azione execute e di conseguenza non ha valutato il sottoinsieme di regole a cui si riferiva. L'errore si è verificato immediatamente dopo, durante l'elaborazione dei risultati complessivi della valutazione del set di regole:
if rule_result.action == "execute" then
rule_result.execute.results = ruleset_results[tonumber(rule_result.execute.results_index)]
end
Il codice del proxy prevedeva che, se un set di regole aveva action="execute", l'oggetto "rule_result.execute" esistesse di default. Poiché la regola è stata ignorata dal killswitch, l'oggetto rule_result.execute non è stato mai creato. Il linguaggio Lua ha quindi restituito un errore nel momento in cui ha tentato di accedere a un valore nullo.
Questo è un errore semplice nel codice, rimasto nascosto per molti anni. Un errore di questo tipo viene prevenuto efficacemente dai linguaggi che utilizzano sistemi di tipi forti. Infatti, il proxy di nuova generazione (FL2), che abbiamo compilato in Rust, non ha riscontrato questo errore.
Quali sono i cambiamenti che sono stati apportati in seguito all'incidente del 18 novembre 2025?
Due settimane fa, precisamente il 18 novembre 2025, avevamo già subito un incidente di disponibilità simile, ma di durata maggiore, causato anch'esso da una modifica non correlata. In entrambi i casi, un aggiornamento volto a migliorare la sicurezza per i nostri clienti si è propagato all'intera rete, generando errori per quasi tutti gli utenti.
Dopo l'incidente precedente, abbiamo parlato direttamente con centinaia di clienti e abbiamo condiviso i piani per introdurre modifiche che impediscano a singoli aggiornamenti di causare un impatto così diffuso. Riteniamo che questi cambiamenti avrebbero potuto contribuire a prevenire le conseguenze dell'incidente odierno, ma purtroppo la loro implementazione non è stata ancora completata.
Siamo consapevoli che è frustrante non aver ancora concluso questo lavoro, che rimane la priorità assoluta per tutta l'organizzazione. Nello specifico, i progetti che descriveremo a breve sono studiati appositamente per contenere l'impatto di modifiche come questa:
Implementazioni e controllo delle versioni migliorati: analogamente a come distribuiamo il nostro software in modo graduale e con una rigorosa convalida dello stato, anche i dati usati per la risposta rapida alle minacce e la configurazione generale necessiteranno delle stesse garanzie di sicurezza e mitigazione. Questo include, tra l'altro, una robusta convalida dello stato e funzionalità di rollback rapido.
Funzionalità di Break Glass semplificate: dobbiamo assicurarci che le operazioni critiche possano comunque essere eseguite anche in caso di disservizi complessi. Questo vale sia per i servizi interni che per tutti i metodi standard di interazione con il piano di controllo di Cloudflare utilizzato da tutti i nostri clienti.
Gestione degli errori "Fail-Open": per aumentare la nostra resilienza, stiamo sostituendo la logica di hard-fail applicata in modo errato in tutti i componenti critici del data-plane di Cloudflare. Se un file di configurazione è danneggiato o fuori dai limiti (ad esempio, supera il numero massimo di feature), il sistema dovrà registrare l'errore, tornare a uno stato ottimale di funzionamento oppure inoltrare il traffico senza applicare la feature problematica, invece di scartare le richieste. Per alcuni servizi, offriremo probabilmente ai clienti la possibilità di scegliere se il fail deve avvenire in modalità "open" o "closed" in scenari specifici. Tutto questo sarà accompagnato da funzionalità di drift-prevention per garantire che la nuova logica venga applicata in modo continuo e coerente.
Entro la fine della prossima settimana, pubblicheremo una ripartizione dettagliata di tutti i progetti di resilienza in corso, compresi quelli che abbiamo appena elencato. In attesa di completare questi lavori, abbiamo bloccato temporaneamente tutte le modifiche alla nostra rete, per assicurarci di implementare sistemi di mitigazione e ripristino migliori prima di riprendere le normali operazioni.
Questo tipo di incidenti e la loro frequenza non sono accettabili per una rete come la nostra. A nome dell'intero team di Cloudflare, desideriamo porgere le nostre scuse per l'impatto e il disagio causati, ancora una volta, ai nostri clienti e a Internet nel suo complesso.
Ora (UTC) | Stato | Descrizione |
08:47 | Inizio dell'INCIDENTE | Modifica alla configurazione distribuita e propagata alla rete |
08:48 | Impatto completo | Modifica completamente propagata |
08:50 | INCIDENTE dichiarato | Avvisi automatizzati |
09:11 | Modifica annullata | Modifica alla configurazione ripristinata e propagazione avviata |
09:12 | Fine dell'INCIDENTE | Ripristino completamente propagato, traffico interamente ripristinato |