23 points par GN⁺ 2025-11-19 | 8 commentaires | Partager sur WhatsApp
  • Le 18 novembre 2025 à 11:20 (UTC), la fonction essentielle d’acheminement du trafic du réseau Cloudflare a été interrompue, entraînant l’affichage de pages d’erreur pour des utilisateurs dans le monde entier
  • La cause est l’augmentation anormale de la taille d’un « fichier de features » du système Bot Management à la suite d’un changement de permissions de base de données, sans lien avec une cyberattaque
  • Cette augmentation de taille a fait que le logiciel de routage du trafic a dépassé sa limite et a échoué, provoquant à grande échelle des erreurs HTTP 5xx
  • Vers 14:30, le déploiement du fichier problématique a été arrêté et remplacé par la version précédente saine, ce qui a permis de rétablir le trafic essentiel ; tous les services sont revenus à la normale à 17:06
  • Cloudflare qualifie cet incident de pire panne depuis 2019 et met en place des mesures de prévention, notamment un renforcement de la validation des fichiers de configuration et l’introduction d’un kill switch global

Vue d’ensemble de la panne

  • Vers 11:20, un échec de l’acheminement du trafic essentiel s’est produit sur le réseau Cloudflare ; les utilisateurs voyaient des pages d’erreur internes de Cloudflare
  • Ni cyberattaque ni acte malveillant n’étaient en cause ; la cause directe était un changement de permissions dans le système de base de données
  • Ce changement a entraîné un doublement de la taille du « fichier de features » utilisé par le système Bot Management, puis sa diffusion sur l’ensemble du réseau
  • Lorsque le logiciel de routage du trafic a lu ce fichier, la limite de taille autorisée a été dépassée, provoquant une erreur système
  • Au départ, l’incident a été pris pour une attaque DDoS de grande ampleur, puis, une fois la cause identifiée, le fichier a été remplacé par la version précédente saine pour lancer la reprise

Déroulement et impact de la panne

  • Avant 11:20, le taux d’erreurs 5xx était normal, puis il a brusquement augmenté après le déploiement du mauvais fichier de features
  • Sur certains nœuds du cluster de base de données ClickHouse, des résultats de requête incorrects étaient générés toutes les 5 minutes ; des fichiers sains et défectueux étaient déployés en alternance, ce qui faisait osciller le système entre reprise et échec
  • À partir de 14:30, la génération du fichier problématique a été arrêtée et un fichier sain a été injecté manuellement, avec reprise via redémarrage du proxy central
  • À 17:06, tous les services étaient revenus à la normale
Service Impact
Core CDN et services de sécurité Erreurs HTTP 5xx
Turnstile Échec de chargement, connexion impossible
Workers KV Forte hausse des erreurs 5xx due à l’échec de la gateway
Dashboard Connexion impossible à cause de la panne de Turnstile
Email Security Baisse temporaire de la précision de détection du spam, échec de certains déplacements automatiques
Access Multiples échecs d’authentification, sessions existantes conservées
  • Pendant l’incident, la latence des réponses CDN a augmenté, en raison d’une forte hausse de l’utilisation CPU des systèmes de débogage

Cause de la panne : système Bot Management

  • Le module Bot Management de Cloudflare utilise des modèles de machine learning pour produire un score de bot pour chaque requête
  • Le fichier de configuration des features utilisé en entrée du modèle est diffusé sur l’ensemble du réseau toutes les quelques minutes pour répondre aux menaces les plus récentes
  • Une modification du comportement d’une requête ClickHouse a provoqué l’inclusion de nombreuses lignes de features dupliquées, augmentant la taille du fichier
  • Cela a provoqué une erreur dans le module Bot Management, qui a alors renvoyé des réponses HTTP 5xx, avec des répercussions aussi sur Workers KV et Access
  • Sur le nouveau moteur proxy FL2, cela a produit des erreurs 5xx ; sur l’ancienne version FL, le score de bot était fixé à 0, augmentant les faux positifs

Changement de comportement des requêtes ClickHouse

  • À 11:05, déploiement d’un changement des permissions d’accès à la base de données de ClickHouse
  • Auparavant, seules les métadonnées de la base default pouvaient être consultées ; après ce changement, celles de la base r0 sont aussi devenues visibles
  • La requête de génération du fichier de features de Bot Management s’exécutait sans filtre sur le nom de la base de données, ce qui a conduit au retour de colonnes en doublon
  • En conséquence, le nombre de lignes du fichier de features a plus que doublé, dépassant les limites du système

Préallocation mémoire et panic système

  • Le module Bot Management applique une limite maximale de 200 features de machine learning et préalloue la mémoire en conséquence
  • Le fichier erroné incluait plus de 200 features, déclenchant un panic dans le code Rust, avec l’erreur
    thread fl2_worker_thread panicked: called Result::unwrap() on an Err value
  • Cela a entraîné une forte vague d’erreurs HTTP 5xx

Autres impacts et processus de reprise

  • Workers KV et Access dépendaient du proxy central, ce qui a amplifié l’impact de la panne
    • À 13:04, un correctif a permis à Workers KV de contourner le proxy, réduisant le taux d’erreur
  • Dashboard dépendait de Turnstile et de Workers KV, rendant la connexion impossible
    • Deux baisses de disponibilité ont eu lieu, de 11:30 à 13:10 puis de 14:40 à 15:30
    • Les files d’attente et les requêtes de nouvelle tentative ont accru la latence, avant un retour à la normale vers 15:30
  • Après 14:30, la majorité des services ont retrouvé un fonctionnement normal, puis la reprise complète a été atteinte à 17:06

Mesures de prévention

  • Renforcement de la validation des entrées des fichiers de configuration générés par Cloudflare
  • Extension des kill switches globaux de fonctionnalités
  • Prévention de l’épuisement des ressources système causé par le reporting d’erreurs
  • Révision des conditions d’erreur dans l’ensemble des modules du proxy central

Résumé de la chronologie (UTC)

Heure État Description
11:05 Normal Déploiement du changement de contrôle d’accès à la base de données
11:28 Début de l’impact Premières erreurs observées sur le trafic client
11:32–13:05 Enquête en cours Analyse de la cause des erreurs Workers KV, tentatives d’atténuation
13:05 Impact réduit Mise en place du contournement pour Workers KV et Access
13:37 Reprise ciblée Préparation du rollback du fichier de configuration Bot Management
14:24 Arrêt du déploiement du fichier problématique Validation terminée du fichier sain
14:30 Impact principal résorbé Déploiement global du fichier sain, début de la reprise des services
17:06 Reprise complète Tous les services sont revenus à la normale

Conclusion

  • Cette panne est due à l’interaction entre la logique de génération du fichier de configuration de Bot Management et un changement de permissions de base de données
  • Cloudflare la considère comme la panne réseau la plus grave depuis 2019
  • L’entreprise prévoit des améliorations structurelles pour renforcer la résilience du système ainsi que des mécanismes de défense automatisés

8 commentaires

 
t7vonn 2025-11-19

Les incidents liés aux fichiers de configuration surviennent partout.

 
princox 2025-11-19

Quand Cloudflare est tombé, toutes sortes de services se sont arrêtés, c’était l’enfer...

 
epdlemflaj 2025-11-19

Le document d’analyse des causes a été publié assez rapidement, dis donc.

 
epdlemflaj 2025-11-19

Au fait, l’auteur de cet article était le CEO.

 
GN⁺ 2025-11-19
Réactions sur Hacker News
  • C’est un incident à plusieurs millions de dollars causé par un .unwrap()
    Appeler .unwrap() sur un chemin d’infrastructure critique d’Internet revient à déclarer : « ça ne peut absolument pas échouer, et si ça échoue, on tue immédiatement le thread ».
    Le compilateur Rust force à exprimer explicitement la possibilité d’un échec, mais ici ils ont choisi le panic au lieu de le gérer proprement.
    À mon avis, c’est un cas typique d’antipattern parse, don’t validate.

    • Beaucoup de gens semblent avoir un angle mort avec .unwrap(). C’est peut-être parce qu’on le voit souvent dans les exemples de code.
      Dans du vrai code d’exploitation, .unwrap() ou .expect() devraient être revus comme des panic.
      Si on utilise .unwrap() en production, il faut obligatoirement un commentaire « INFALLIBILITY », et on peut l’imposer avec clippy::unwrap_used.
    • Le point principal de cet article semble être que le problème vient moins d’une cause unique que d’une combinaison de composants normaux.
      Ce n’est pas simplement à cause de .unwrap(), mais aussi parce que la requête ne séparait pas les bases de données, ce qui a grossi le payload, et parce que ClickHouse exposait davantage de bases.
      Plutôt que de conclure « c’est la faute de unwrap », je pense qu’il est plus important d’améliorer la conception pour éviter qu’un kill switch global ou qu’un composant n’épuise les ressources système.
    • En réalité, ça aurait aussi échoué hors du chemin Rust. Le système de gestion des bots classait tout le trafic comme bot.
      La couche FL2 devrait intercepter les panic de chaque composant, mais le fail-open n’est pas toujours préférable.
      Il faudrait ajouter une logique permettant de décider explicitement au niveau FL2 s’il faut intercepter et traiter un panic.
    • Si cela avait été géré proprement, il y aurait probablement eu une baisse de performances (mais c’est quand même préférable à une baisse de fiabilité, à mon avis).
      Dans un système shardé, je me demande aussi pourquoi il n’y avait ni déploiement progressif ni monitoring.
    • Swift a le déballage implicite avec ! et le déballage explicite avec ?.
      Je n’utilise presque jamais le déballage implicite. Même pour une valeur garantie, je la traite toujours explicitement.
      Par exemple, je définirais @IBOutlet weak var someView? plutôt que @IBOutlet weak var someView!.
      C’est une approche ceinture et bretelles.
  • Publier un post mortem moins de 24 heures après la panne, c’est vraiment impressionnant.

    • Je me demande quelle politique interne permet de publier quelque chose d’aussi vite et avec autant de transparence.
      Dans la plupart des grandes entreprises, la publication du code serait presque impossible à cause des validations de multiples stakeholders.
    • En plus, le texte lui-même est bien écrit. Comparé aux post-mortems d’AWS, c’est presque de la littérature.
  • En lisant l’explication de Cloudflare sur la panne, je me suis demandé : « pourquoi la restauration a-t-elle pris autant de temps ? »
    J’ai compris la cause de la panne, mais si la majeure partie du réseau est tombée, on pourrait penser que revenir sur le dernier changement de configuration est la priorité absolue.
    Bien sûr, c’est évident après coup, mais le fait qu’ils aient commencé l’enquête en 7 minutes est impressionnant.

    • Au début, ils ont cru à une attaque. Ensuite ils ont compris le problème, mais il n’y avait aucun moyen de remplacer le fichier corrompu dans la file, et ils ont dû redémarrer un très grand nombre de machines dans le monde entier.
  • Cet incident rappelle l’accident CrowdStrike.
    Un fichier de configuration généré automatiquement a cassé le logiciel, puis a été propagé à l’ensemble du réseau.
    Je comprends qu’il faille pouvoir déployer vite, mais cette affaire révèle l’absence de déploiement progressif et de stratégie de rollback.

    • Il faut sans doute voir cela moins comme un déploiement CI/CD que comme le canal de contrôle d’un système distribué de détection de bots.
    • Je suis surpris qu’ils aient poussé directement en production sans simulateur.
    • Malgré tout, je pense que cet incident mènera à des améliorations.
  • Quand on regarde le plan d’amélioration annoncé par Cloudflare :

    • Renforcement de la validation des fichiers de configuration générés par Cloudflare
    • Ajout d’un kill switch global
    • Prévention de l’épuisement des ressources causé par les core dumps ou les rapports d’erreur
    • Réexamen des modes d’erreur du module proxy
      figurent bien dans la liste.
      Mais il manque les déploiements canary ou les déploiements progressifs de configuration.
      Un switch global peut être dangereux, et un seul bug peut arrêter tout le système.
    • Les configurations de gestion des bots doivent se propager vite, mais s’ils avaient d’abord testé sur une instance, ils auraient détecté le panic à l’avance.
      Je me demande aussi pourquoi ClickHouse a été utilisé comme magasin de feature flags. La documentation ClickHouse sur la déduplication mentionne elle aussi des risques.
    • Le service de configuration avait bien un déploiement progressif, mais les services consommateurs se mettaient à jour automatiquement trop souvent, si bien qu’un faible pourcentage d’erreurs a fini par affecter tout le monde.
    • Les configurations globales sont utiles pour réagir vite, mais un mécanisme de rollback rapide est indispensable.
      Une cartographie des dépendances entre services rendrait aussi la recherche de la cause bien plus simple.
    • En fin de compte, la plupart des grandes pannes viennent de config push.
      Les déploiements de code sont prudents, mais pas les déploiements de configuration. Il faut considérer que la configuration est aussi du code.
  • Le passage indiquant que la page de statut est tombée et qu’ils ont cru à une attaque est intéressant.
    Ils disent qu’elle est totalement séparée de l’infrastructure Cloudflare, mais rien n’explique pourquoi elle est tombée elle aussi.

    • Il est probable qu’il s’agisse simplement d’un échec de montée en charge de l’infrastructure à cause d’un pic de trafic.
    • En pratique, ils pensaient peut-être ne pas dépendre de Cloudflare, mais comme une grande partie d’Internet dépend de CloudFront, ce n’était peut-être pas totalement indépendant.
    • Pour connaître la cause, il faudrait le post mortem de statuspage.io. C’est un service exploité par Atlassian.
    • Il se peut aussi que l’ampleur même de Cloudflare ait simplement provoqué un afflux massif de trafic.
  • J’ai intégré Turnstile avec une stratégie fail-open, et cela a aidé pendant cette panne.
    Si le JS ne se charge pas, j’autorise l’envoi avec un jeton factice, et côté backend, si la validation échoue, je traite aussi en fail-open.
    Certains utilisateurs ont quand même été bloqués, mais l’impact global a été réduit.
    C’est une approche rendue possible par d’autres mesures d’atténuation contre les bots.

    • On peut alors se demander si un attaquant ne pourrait pas simplement bloquer le script pour contourner le CAPTCHA.
      Mais cela ne semble fonctionner que si l’attaque n’est pas ciblée.
  • Je me demande pourquoi Cloudflare autorisait .unwrap() dans son code.
    À minima, ils auraient dû utiliser expect("cela ne devrait jamais arriver").
    La philosophie consistant à traiter les erreurs comme des valeurs est précisément censée éviter ce genre de problème, et cela aurait rendu le diagnostic bien plus facile.

    • Je ne travaille pas chez Cloudflare, mais j’utilise beaucoup Rust.
      Dans du code impliquant des appels réseau, il y a bien trop de possibilités d’échec.
      J’utilise .unwrap() pendant le développement, mais en production il m’arrive de laisser des expect(), parce qu’il n’y a parfois tout simplement plus aucun moyen d’aller plus loin.
  • La vraie leçon, c’est que trop de fonctionnalités dépendent d’un petit nombre d’acteurs.
    La logique du winner-takes-all s’accentue, et la résilience du système en souffre.
    Bien sûr, ils ont mérité leur position, mais attendre d’Internet qu’il soit toujours « en état de marche » me paraît excessif.

  • Dire que « Rust rend tout sûr » est exagéré.
    Quel que soit le langage, mal l’utiliser revient à braquer l’arme sur son propre pied.

 
barca105 2025-11-19

Même une entreprise comme CF utilise .unwrap()… wow. Comment ce code a-t-il pu être déployé en production ?

 
skageektp 2025-11-19

On dirait que unwrap n’est pas le problème

 
barca105 2025-11-19

Le problème fondamental, c’est la requête erronée.
Mais je pense aussi que le fait d’avoir sauté la validation du problème avec unwrap est en soi un problème.
Même si un souci survenait en interne, si l’erreur avait été gérée, le trafic ne serait sans doute pas tombé.