Lecture: 5 min.
Le 5 décembre 2025 à 8 h 47 UTC (toutes les heures mentionnées dans ce blog sont au format UTC), une partie du réseau Cloudflare a commencé à connaître des défaillances significatives. L'incident a été résolu à 9 h 12 avec le rétablissement complet de l'ensemble des services (au total, le problème s'est donc fait sentir pendant environ 25 minutes).
Le sous-ensemble de clients affectés totalisait près de 28 % de l'ensemble du trafic HTTP diffusé par Cloudflare. La réunion de plusieurs facteurs était nécessaire pour qu'un client particulier soit touché selon les modalités décrites ci-après.
Le dysfonctionnement ne résultait en aucune façon d'une cyberattaque ou d'une quelconque activité malveillante sur les systèmes Cloudflare, ni directement ni indirectement. Il découlait de modifications que nous avons apportées à notre logique d'analyse du corps des requêtes lors d'une tentative visant à détecter et à atténuer une vulnérabilité des React Server Components (composants serveur React) révélée cette semaine et affectant l'ensemble du secteur.
Toute forme d'interruption de nos systèmes est inacceptable et nous savons que nous avons encore une fois déçu la communauté Internet après l'incident déjà survenu le 18 novembre. Restez à l'écoute de nos canaux la semaine prochaine, nous publierons des informations détaillées sur les mesures que nous comptons prendre pour éviter que ce type de dysfonctionnement se reproduise.
Le graphique ci-dessous présente le nombre d'erreurs HTTP 500 émises par notre réseau sur l'ensemble de la période de l'incident (ligne rouge en bas) par rapport au trafic Cloudflare total non affecté par le problème (ligne verte en haut).
Le pare-feu applicatif web (Web Application Firewall, WAF) de Cloudflare assure une protection contre le contenu malveillant à nos clients afin de leur permettre de détecter et de bloquer ce dernier. Pour ce faire, le proxy Cloudflare place le contenu du corps de la requête HTTP en mémoire tampon afin de procéder à son analyse. La taille du tampon était jusqu'ici de 128 Ko.
Dans le cadre des efforts que nous menons pour protéger nos clients utilisateurs de React contre la vulnérabilité critique dénommée CVE-2025-55182, nous avons commencé à déployer une augmentation de la taille de notre mémoire tampon à 1 Mo, la limite autorisée par défaut pour les applications Next.js afin de nous assurer de protéger le plus grand nombre de clients possible.
L'implémentation de cette première modification a été confiée à notre système de déploiement progressif. Nous avons remarqué lors du déploiement que notre outil interne chargé de tester le pare-feu WAF ne prenait pas en charge l’augmentation de la taille de la mémoire tampon. Comme cet outil de test interne n’était pas nécessaire à l’époque et qu’il n’affectait en aucune façon le trafic de nos clients, nous avons procédé à une deuxième modification afin de le désactiver.
Cette deuxième modification visant à désactiver notre outil de test du pare-feu WAF a été déployée à l'aide de notre système de configuration mondial. Ce système ne procède pas par déploiements progressifs, mais propage les modifications en quelques secondes à l’ensemble de la flotte de serveurs qui composent notre réseau. Il est d'ailleurs toujours en cours d'examen suite au dysfonctionnement survenu le 18 novembre.
Malheureusement, certaines circonstances entourant le déploiement de cette deuxième modification (conçue, rappelons-le, pour désactiver notre outil de test des règles WAF) au sein de la version FL1 de notre proxy ont entraîné une erreur, qui a abouti à l’émission de codes d’erreur HTTP 500 depuis notre réseau.
Lorsque la modification s'est propagée à notre réseau, l'exécution du code au sein de notre proxy FL1 a débouché sur un bug présent dans notre module de règles, qui a conduit à l'exception Lua suivante :
[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)
Le système a dès lors émis des erreurs de code HTTP 500 en conséquence.
Identifiée peu après l'application, la modification à l'origine du problème a été annulée à 9 h 12, suite à quoi l'intégralité du trafic est revenu à la normale.
Seuls les clients dont les ressources web sont traitées par notre ancien proxy FL1 ET qui avaient déployé l'ensemble de règles gérées Cloudflare ont été touchés. Toutes les requêtes adressées aux sites web concernés ont renvoyé un message d'erreur HTTP 500, mis à part un petit nombre de points de terminaison dédiés aux tests, comme /cdn-cgi/trace, par exemple.
Les clients qui ne disposaient pas de la configuration présentée ci-dessus n'ont pas été affectés. De même, le trafic client traité par le réseau Chine n'a pas non plus été touché.
L'erreur au sein de l'environnement d'exécution
La plateforme Cloudflare consiste en plusieurs ensembles de règles évalués lors de l'entrée d'une requête au sein de notre système (chacune de ces requêtes en fait). Ces règles se composent d'un filtre (qui sélectionne un certain trafic) et d'une action qui applique un effet au trafic sélectionné. Les actions généralement mises en œuvre sont « block » (Bloquer), « log » (Journaliser) ou « skip » (Ignorer). Un autre type d'action est l'action « execute » (Exécuter), utilisée pour déclencher l'évaluation d'un autre ensemble de règles.
Notre système de journalisation interne s'appuie sur cette fonctionnalité pour évaluer les nouvelles règles avant de les proposer au public. Un ensemble de règles de niveau supérieur exécutera un autre ensemble contenant des règles de test. Ce sont ces dernières que nous avons tenté de désactiver.
Nous avons intégré un sous-système d'arrêt d'urgence (également appelé « killswitch ») au système d'ensembles de règles. Ce dispositif est conçu pour permettre la désactivation rapide d'une règle qui présenterait un comportement anormal. Le killswitch reçoit des informations de la part du système de configuration mondial que nous mentionnons dans les sections précédentes. Nous avons utilisé ce système d'arrêt d'urgence plusieurs fois par le passé pour atténuer des incidents et disposons d'une procédure opérationnelle standard bien définie concernant son fonctionnement. La procédure a d'ailleurs été suivie à la lettre lors de l'incident.
Nous n'avions toutefois jamais appliqué ce killswitch à une règle accompagnée de l'action type « execute ». Le code a ainsi correctement ignoré l'évaluation de l'action Exécuter lorsque le système d'arrêt d'urgence a été enclenché et n'a pas évalué le sous-ensemble de règles désigné par cette action. Or, une erreur est survenue lors du traitement des résultats généraux de l'évaluation de l'ensemble de règles.
if rule_result.action == "execute" then
rule_result.execute.results = ruleset_results[tonumber(rule_result.execute.results_index)]
end
Ce code s'attend à ce que l'objet « rule_result.execute » existe si l'ensemble de règles a comme action « execute ». Toutefois, comme la règle avait été ignorée, l'objet rule_result.execute n'existait pas et le système Lua a renvoyé une erreur, car il tentait de rechercher une valeur nulle.
Cette simple erreur au sein du code existe probablement depuis de nombreuses années, mais n'avait jamais été détectée jusqu'ici. Les langages dotés de systèmes de typage forts permettent d'éviter ce type d'erreur de code. Cette erreur ne s'est ainsi pas produite au sein de notre nouveau proxy FL2 (dont le code a été remplacé par un code rédigé en Rust).
Qu'en est-il des modifications effectuées après l'incident du 18 novembre 2025 ?
Un incident de disponibilité plus long, mais néanmoins similaire, s'est produit il y a deux semaines (le 18 novembre 2025) suite au déploiement par nos services d'une modification sans lien avec le problème qui nous occupe aujourd'hui. Le problème résultait, dans les deux cas, du déploiement d'un correctif visant à atténuer un problème de sécurité pour nos clients. La modification s'est ensuite propagée à l'ensemble de notre réseau et a conduit à des erreurs pour pratiquement tous nos clients.
Nous avons parlé directement à des centaines de clients à la suite de cet incident et les avons informés de notre volonté de procéder à des changements au sein de notre plateforme afin d'empêcher qu'une simple mise à jour n'entraîne d'aussi nombreuses conséquences. Nous pensons que ces changements auraient permis d'éviter les effets de l'incident d'aujourd'hui, mais nous n'avons malheureusement pas encore terminé de les déployer.
Nous savons qu'il est décevant d'apprendre que ces travaux ne sont pas encore achevés, mais ils demeurent toutefois une priorité absolue pour l'ensemble de notre entreprise. Les projets décrits ci-dessous devraient notamment contribuer à limiter l'incidence de ce type de modifications :
Amélioration des processus de déploiement et de gestion des versions : les données utilisées pour la réponse rapide aux menaces et la configuration générale doivent bénéficier des mêmes fonctionnalités de sécurité et d'atténuation des risques sur lesquelles nous nous appuyons lorsque nous déployons des logiciels, de manière lente et mesurée, avec un strict processus de validation de l'intégrité. Outre la validation de l'intégrité, ces fonctionnalités comprennent, entre autres, des capacités de restauration rapide.
Rationalisation des fonctionnalités d'urgence (break-glass) : nous devons nous assurer d'être toujours à même de réaliser nos opérations essentielles, malgré les autres types de défaillances qui pourraient se produire. Ce plan s'applique aux services internes, mais aussi aux méthodes standard d'interaction avec l'interface Cloudflare utilisée par l'ensemble de nos clients.
Traitement « fail-open » des erreurs : dans le cadre de nos efforts d'amélioration de notre résilience, nous remplaçons la logique incorrectement mise en œuvre de gestion des erreurs de type « hard-fail » (échec total, sans basculement) pour tous les composants essentiels du plan de données Cloudflare. Ainsi, en cas de corruption d'un fichier de configuration ou de fonctionnement hors plage de ce dernier (en cas de dépassement des limites d'une fonctionnalité, par exemple), le système journalise l'erreur et, plutôt que d'abandonner les requêtes, revient par défaut à un état correct connu ou transmet le trafic sans lui attribuer de score. Certains services permettront probablement au client de choisir entre le basculement en position ouverte (fail-open) ou fermée (fail-closed) dans certains scénarios de défaillance. Ces nouvelles mesures comprendront des fonctionnalités de prévention des dérives afin d'assurer leur application en continu.
Nous publierons une analyse détaillée de l'ensemble des projets d'amélioration de la résilience actuellement en cours (notamment de ceux présentés ci-dessus) avant la fin de la semaine prochaine. Nous verrouillerons le déploiement de toutes les modifications apportées à notre réseau pendant ces travaux afin de nous assurer que nous disposons de meilleurs systèmes d'atténuation et de restauration avant de reprendre les opérations.
Les incidents de ce type (de même que la proximité temporelle de ces derniers) ne sont pas acceptables pour un réseau comme le nôtre. Au nom de toute l'équipe Cloudflare, nous tenons à vous présenter nos excuses pour les effets néfastes et les désagréments que ce problème a (de nouveau) causé à nos clients et à l'ensemble de l'Internet.
Heure (UTC) | État | Description |
8 h 47 | Début de L'INCIDENT | Déploiement et propagation au réseau de la modification de la configuration |
8 h 48 | Impact maximal | Propagation totale de la modification |
8 h 50 | Déclaration de L'INCIDENT | Émission d'alertes automatisées |
9 h 11 | Annulation de la modification | Annulation de la modification apportée à la configuration et démarrage de la propagation |
9 h 12 | Fin de L'INCIDENT | Fin de la propagation de la mesure d'annulation, rétablissement de l'ensemble du trafic |