Résumé

  • L'incident d'accès non autorisé de Docker Hub en 2019 est devenu un test de responsabilité de la chaîne d'approvisionnement des conteneurs car des rapports publics ont reproduit l'avis de Docker indiquant qu'une seule base de données Hub stockant un sous-ensemble de données utilisateur non financières avait été consultée, environ 190 000 comptes peuvent avoir été exposés, et les jetons GitHub et Bitbucket pour les autobuilds Docker étaient concernés.
  • Qui avait le contrôle pratique sur le stockage des jetons d'accès, la délimitation de l'intégration des dépôts, la notification des clients, l'invalidation des jetons, la confiance dans les builds automatisés et la preuve qu'un incident de registre ne pouvait pas devenir silencieusement une compromission plus large de la chaîne d'approvisionnement logicielle?
  • Les archives publiques confirmées disponibles via BleepingComputer àhttps://www.bleepingcomputer.com/news/security/docker-hub-database-hack-exposes-sensitive-data-of-190k-users/et l'avis utilisateur conservé àhttps://news.ycombinator.com/item?id=19763413soutiennent la séquence d'exposition, de réinitialisation, de reconnexion et de révision des journaux de sécurité, tandis que la documentation actuelle de Docker explique le modèle de build automatisé et de jetons.
  • L'inférence soutenue est que l'incident n'était pas seulement un événement de sécurité de compte. Parce que les builds automatisés de Docker Hub relient Docker Hub aux fournisseurs de code source, l'exposition des jetons a créé une question de gouvernance à travers GitHub, Bitbucket, Docker Hub, CI/CD, la publication d'images et la consommation d'images en aval.
  • Des inconnues persistent: les archives publiques ne fournissent pas le rapport médico-légal complet de Docker, le schéma exact de la base de données, la portée des jetons pour chaque compte, les journaux d'accès des fournisseurs de code source, la preuve de l'absence de modification des dépôts, la population notifiée ou la preuve de chaque action de correction du client.

Pourquoi ce cas figure dans un dossier de risque et de responsabilité

Docker Hub figure dans un dossier de risque et de responsabilité car les registres de développement ne stockent pas seulement des artefacts. Ils connectent des identités, des dépôts, des règles de build, des jetons, des images, des tags, des webhooks et des habitudes de déploiement en aval. Lorsque le registre indique que des jetons de fournisseur de code source peuvent avoir été exposés, la surface de responsabilité s'étend immédiatement au-delà du compte du registre. Elle atteint les dépôts de code qui alimentent les builds et les images que les équipes intègrent dans le développement, les tests et la production.

Le meilleur dossier public d'incident n'est pas une page d'avis Docker actuellement en ligne. L'ancienne URL de support Docker citée dans les rapports de 2019 n'est plus une source fiable en ligne. Le dossier public est donc construit à partir du texte d'avis utilisateur reproduit et des reportages contemporains. BleepingComputer a rapporté àhttps://www.bleepingcomputer.com/news/security/docker-hub-database-hack-exposes-sensitive-data-of-190k-users/que Docker a eu connaissance d'un accès non autorisé à une base de données Docker Hub le 25 avril 2019 et que les données concernées comprenaient des noms d'utilisateur, des mots de passe hachés pour un petit pourcentage d'utilisateurs, et des jetons GitHub et Bitbucket utilisés pour les autobuilds Docker. Le même article a reproduit le texte de notification aux utilisateurs. Un article conservé sur Hacker News àhttps://news.ycombinator.com/item?id=19763413montre le langage de l'avis, y compris les déclarations selon lesquelles environ 190 000 comptes peuvent avoir été exposés, moins de 5 % des utilisateurs de Hub, et que Docker a révoqué les jetons GitHub et les clés d'accès pour les utilisateurs d'autobuild concernés.

Ce sont les faits confirmés sur lesquels cet article s'appuie: un accès non autorisé à une base de données Docker Hub a été signalé; un sous-ensemble de données utilisateur non financières était concerné; environ 190 000 comptes peuvent avoir été exposés; certains noms d'utilisateur et mots de passe hachés étaient inclus; des jetons GitHub et Bitbucket pour les autobuilds Docker étaient inclus; Docker a demandé aux utilisateurs de changer leurs mots de passe le cas échéant; Docker a déclaré avoir révoqué les jetons et clés d'accès concernés; Docker a demandé aux utilisateurs d'autobuild de reconnecter leurs dépôts et de vérifier les journaux de sécurité des fournisseurs de code source. Security Affairs àhttps://securityaffairs.com/84554/data-breach/docker-data-breach.html, The Hacker News àhttps://thehackernews.com/2019/04/docker-hub-data-breach.htmlet Help Net Security àhttps://www.helpnetsecurity.com/2019/04/29/docker-hub-breach/ont rapporté la même séquence de base.

L'inférence soutenue est qu'il s'agissait d'un événement de gouvernance de la chaîne d'approvisionnement, même si aucune source publique ne prouve une compromission en aval. La documentation actuelle de Docker sur les builds automatisés àhttps://docs.docker.com/docker-hub/repos/manage/builds/explique que Docker Hub peut automatiquement construire des images à partir de dépôts de code source et pousser les images construites vers les dépôts Docker. La documentation sur la liaison de source àhttps://docs.docker.com/docker-hub/repos/manage/builds/link-source/explique que les utilisateurs lient des fournisseurs de code source GitHub ou Bitbucket pour que Docker Hub puisse accéder aux dépôts de code source. La page de configuration àhttps://docs.docker.com/docker-hub/repos/manage/builds/setup/indique que les builds automatisés peuvent construire une image lorsque du code est poussé vers un fournisseur de code source. Cette conception fait des jetons de fournisseur de code source une partie de la chaîne de build, pas seulement une commodité de compte.

Les inconnues restent matérielles. Les archives publiques n'identifient pas l'acteur non autorisé, la méthode d'accès, les champs de la base de données, toutes les permissions des jetons, si un jeton a été utilisé, si un dépôt de code source a été modifié, si une image a été reconstruite avec des modifications non autorisées, ou comment Docker a vérifié l'absence ou la présence d'un usage abusif. Cet article évite donc les accusations non étayées. Il ne dit pas que les images Docker Hub ont été empoisonnées, que le code source a été modifié ou que Docker a dissimulé une compromission plus large.

Il dit que l'exposition de jetons dans une plateforme de build automatisé a créé un devoir de responsabilité de prouver la révocation, la délimitation, l'action du client et l'intégrité de la chaîne de build.

Faits confirmés, inférence soutenue et inconnues

La chronologie publique confirmée commence le 25 avril 2019, lorsque l'avis de Docker a déclaré avoir découvert un accès non autorisé à une seule base de données Hub. Le langage de l'avis conservé àhttps://news.ycombinator.com/item?id=19763413indiquait que la base de données stockait un sous-ensemble de données utilisateur non financières et que Docker avait agi pour intervenir et sécuriser le site. L'avis indiquait que des données sensibles d'environ 190 000 comptes pouvaient avoir été exposées. Il décrivait cette population comme moins de 5 % des utilisateurs de Hub. Il identifiait les classes de données comme les noms d'utilisateur et les mots de passe hachés pour un petit pourcentage d'utilisateurs, plus les jetons GitHub et Bitbucket pour les autobuilds Docker.

La séquence de réparation publique confirmée comporte trois niveaux. Premièrement, Docker a demandé aux utilisateurs concernés de changer leur mot de passe Docker Hub et tout autre mot de passe de compte qui le partageait. Deuxièmement, pour les utilisateurs d'autobuild qui pouvaient avoir été concernés, Docker a déclaré avoir révoqué les jetons GitHub et les clés d'accès et a demandé aux utilisateurs de reconnecter leurs dépôts. Troisièmement, Docker a demandé aux utilisateurs de vérifier les journaux de sécurité GitHub et Bitbucket pour des actions inattendues.

L'avis indiquait également que les builds en cours pouvaient être affectés et que les utilisateurs pourraient devoir délier et relier les fournisseurs de code source GitHub et Bitbucket.

L'inférence soutenue est que Docker a correctement traité l'invalidation des jetons comme plus importante qu'une simple réinitialisation de mot de passe. L'exposition du mot de passe menace le compte Docker Hub. L'exposition des jetons de fournisseur de code source menace le pont entre Docker Hub et le dépôt de code. Ce pont peut avoir des implications de lecture ou d'écriture selon les permissions du fournisseur et le modèle d'intégration. La documentation OAuth de GitHub àhttps://docs.github.com/en/apps/oauth-apps/using-oauth-apps/reviewing-your-authorized-oauth-appsavertit les utilisateurs de vérifier les applications autorisées et de rechercher des permissions étendues, y compris l'accès aux dépôts privés. La documentation du journal de sécurité de GitHub àhttps://docs.github.com/en/authentication/keeping-your-account-and-data-secure/reviewing-your-security-logexplique que les utilisateurs peuvent examiner les actions impliquant leur compte. Les conseils sur les journaux d'audit Bitbucket Cloud àhttps://support.atlassian.com/bitbucket-cloud/kb/bitbucket-cloud-audit-log-events/expliquent que les journaux d'audit de l'espace de travail suivent les activités clés. Ces sources soutiennent le modèle de réparation pratique: révoquer, reconnecter, vérifier les journaux et confirmer.

Les inconnues définissent la limite du jugement. Les archives publiques n'incluent pas de liste des clients concernés, les portées complètes des jetons, la preuve que chaque jeton révoqué n'avait pas été utilisé, une corrélation complète des journaux GitHub ou Bitbucket, une liste des builds échoués en raison de la révocation, ou un rapport technique post-incident. Il n'est pas non plus clair d'après les preuves publiques si tous les utilisateurs concernés comprenaient la différence entre changer un mot de passe Docker et vérifier les dépôts du fournisseur de code source.

Ce manque de communication importe car un usage abusif du fournisseur de code source, s'il s'était produit, aurait été visible d'abord dans l'activité GitHub ou Bitbucket, pas nécessairement dans Docker Hub.

La garde des jetons a fait du registre une dépendance de contrôle de code source

La question centrale de responsabilité est la garde des jetons. Un registre qui propose des builds automatisés demande aux développeurs de connecter des fournisseurs de code source. Cette connexion est précieuse car elle réduit le travail manuel. Une poussée vers GitHub ou Bitbucket peut déclencher un build Docker Hub, et l'image résultante peut être poussée vers le registre pour une utilisation en aval. Mais la même connexion crée une obligation de garde. Docker Hub détient ou contrôle des identifiants qui peuvent affecter l'accès au code source et le comportement de build.

Lorsque ces identifiants sont exposés, l'incident du registre franchit le risque de contrôle de code source.

La documentation actuelle de Docker montre toujours la forme de cette dépendance. L'aperçu des builds automatisés àhttps://docs.docker.com/docker-hub/repos/manage/builds/indique que Docker Hub peut automatiquement construire des images à partir de code source dans un dépôt externe et pousser l'image construite vers les dépôts Docker. La page de liaison de source àhttps://docs.docker.com/docker-hub/repos/manage/builds/link-source/indique que les utilisateurs lient un service de code source hébergé à Docker Hub pour que Docker Hub puisse accéder aux dépôts de code source. La page de configuration àhttps://docs.docker.com/docker-hub/repos/manage/builds/setup/nomme GitHub et Bitbucket comme fournisseurs de code source. Ces pages sont de la documentation produit actuelle, pas des preuves d'incident de 2019, mais elles expliquent pourquoi les jetons de fournisseur de code source sont des objets de grande valeur.

Pour un développeur, le chemin d'automatisation semble normal. Configurer le fournisseur de code source. Définir les règles de build. Laisser les poussées déclencher des images. Tirer l'image plus tard. Pour un analyste de responsabilité, le chemin est une chaîne de garde. Qui peut autoriser le fournisseur de code source? Quelles portées sont demandées? Les jetons sont-ils liés à l'utilisateur, à l'équipe ou à un compte de service? Sont-ils stockés cryptés? Sont-ils tournés? Sont-ils révocables à grande échelle? Les builds sont-ils signés ou autrement attestables? Les tags d'image sont-ils mutables?

Les journaux sont-ils conservés assez longtemps pour reconstruire une reconstruction suspecte? Ces questions deviennent urgentes après une exposition de jetons.

L'avis Docker, tel que reproduit publiquement, a répondu à certaines questions par des actions. Les jetons ont été révoqués. Les utilisateurs ont été invités à reconnecter. Les journaux de sécurité ont été nommés. Une surveillance supplémentaire a été mise en place. C'est une première réponse crédible. Mais elle n'a pas prouvé la chaîne complète.

Elle n'a pas montré quelles permissions les jetons exposés avaient, combien de temps l'accès non autorisé a duré, si des dépôts de code source ont vu un accès depuis des adresses inattendues, si des sorties de build ont changé, ou si Docker pouvait corréler chaque jeton avec l'activité du fournisseur de code source.

Cette distinction explique pourquoi l'événement n'est pas seulement une histoire de notification de brèche. C'est une histoire de contrôle de plateforme de développement. Un registre qui stocke des jetons d'intégration de build doit pouvoir répondre non seulement « quelles données de compte ont été exposées? » mais « cette exposition a-t-elle pu changer du code, changer des images ou changer ce que les systèmes en aval ont déployé? » La réponse peut être non. Mais le dossier responsable nécessite des preuves.

Les builds automatisés ont transformé la commodité en rayon d'explosion

Les builds automatisés sont une fonctionnalité de productivité classique avec un coût caché de résilience. La documentation de Docker àhttps://docs.docker.com/docker-hub/repos/manage/builds/décrit une règle de branche ou de tag déclenchant un build lorsque le code source change. Le build produit ensuite une image et la pousse vers Docker Hub. Cela réduit les frictions de publication manuelle. Cela signifie également qu'un identifiant attaché au chemin d'automatisation peut se trouver en amont d'un artefact publié. Si l'identifiant est sur-étendu, à longue durée de vie, lié à un utilisateur puissant ou faiblement surveillé, une compromission du registre peut créer une incertitude sur le contrôle de code source et l'intégrité des images.

L'incident de 2019 n'a pas prouvé publiquement de publication d'image malveillante. Le point responsable est que la possibilité devait être enquêtée. BleepingComputer àhttps://www.bleepingcomputer.com/news/security/docker-hub-database-hack-exposes-sensitive-data-of-190k-users/a averti que les jetons pouvaient permettre l'accès au code des dépôts privés et une modification possible selon les permissions. Cette déclaration est formulée comme un scénario de risque, pas un résultat confirmé. Help Net Security àhttps://www.helpnetsecurity.com/2019/04/29/docker-hub-breach/a également souligné le danger des jetons. Un article discipliné devrait garder cette limite: l'exposition des jetons a créé un risque pour la chaîne d'approvisionnement; les preuves publiques ne montrent pas que ce risque s'est matérialisé.

L'implication de la réparation est exigeante. La réinitialisation du mot de passe ne suffit pas. La révocation des jetons est nécessaire mais pas suffisante. La reconnexion peut restaurer les builds, mais elle peut aussi cacher un travail d'audit manqué si les équipes se précipitent pour rendre les pipelines verts. Un client responsable devait vérifier les journaux de sécurité GitHub àhttps://docs.github.com/en/authentication/keeping-your-account-and-data-secure/reviewing-your-security-log, vérifier les applications OAuth autorisées àhttps://docs.github.com/en/apps/oauth-apps/using-oauth-apps/reviewing-your-authorized-oauth-apps, vérifier les journaux d'audit Bitbucket àhttps://support.atlassian.com/bitbucket-cloud/kb/bitbucket-cloud-audit-log-events/, et révoquer ou remplacer les jetons d'accès compromis le cas échéant en utilisant des conseils tels quehttps://support.atlassian.com/bitbucket-cloud/docs/revoke-a-workspace-access-token/.

C'est une charge opérationnelle lourde pour l'utilisateur. La brèche de la plateforme devient le projet d'audit du client. Les mainteneurs doivent vérifier les journaux des fournisseurs de code source, enquêter sur les accès inattendus, tourner les identifiants, relier les fournisseurs, confirmer qu'aucune image n'a été construite à partir de modifications non autorisées du code source, et informer les équipes en aval si les tags d'image peuvent toujours être fiables. L'avis peut demander aux utilisateurs d'effectuer ce travail, mais la plateforme doit reconnaître qu'il s'agit d'un coût transféré.

C'est particulièrement difficile pour les mainteneurs open source et les petites équipes. Les grandes entreprises peuvent avoir des journaux, une intégration SIEM, une gouvernance des dépôts et des playbooks de réponse aux incidents. Un mainteneur bénévole peut avoir un compte Docker Hub personnel lié à un dépôt GitHub, une visibilité limitée des journaux et des utilisateurs en aval qui tirent des images sans contact direct. L'économie des outils de développement encourage la commodité et la faible friction. La responsabilité exige de traiter le patrimoine de jetons résultant comme une infrastructure de production.

L'avis a transféré le travail de réparation aux mainteneurs

L'avis Docker, tel que reproduit publiquement, a fait plus qu'annoncer l'exposition. Il a assigné du travail. Les utilisateurs devaient changer les mots de passe le cas échéant, relier les fournisseurs de code source, vérifier les journaux de sécurité et récupérer les builds automatisés cassés. C'était une réponse raisonnable à un incident de jetons, mais elle a également déplacé le coût vers les mainteneurs et les organisations. La partie qui contrôlait la base de données compromise pouvait révoquer les jetons et envoyer un avis. Les parties qui contrôlaient les dépôts de code source devaient prouver si le pont exposé avait été utilisé.

Cela importe car les mainteneurs diffèrent fortement en capacité. Une entreprise avec des contrôles d'audit d'organisation GitHub, des journaux d'espace de travail Bitbucket, une administration d'organisation Docker et une surveillance CI/CD peut constituer un dossier de preuves. Elle peut demander qui a autorisé l'application, quelles permissions de dépôt ont été accordées, quels jetons ont été révoqués, quels jobs de build ont échoué et si des commits sources ou des tags d'image ont changé dans la fenêtre. Un mainteneur individuel peut voir seulement un email déroutant, un build automatisé cassé et une demande de vérification des journaux.

Le même incident crée donc une charge de réparation inégale dans tout l'écosystème.

La charge de réparation s'étend également aux utilisateurs en aval qui n'ont jamais reçu l'avis original. Une entreprise qui tire une image publique peut ne pas savoir si le compte Docker Hub du mainteneur était concerné. Un mainteneur peut ne pas connaître chaque consommateur en aval. Une plateforme de registre peut connaître l'exposition au niveau du compte mais pas chaque copie déployée d'une image. C'est la raison structurelle pour laquelle les incidents de jetons dans les plateformes de développement méritent une analyse de la chaîne d'approvisionnement. L'exposition directe est mesurée en comptes.

L'effet de confiance est mesuré en artefacts, dépendances et hypothèses.

L'avis responsable devrait donc faire trois choses. Il devrait identifier clairement le compte et l'intégration concernés. Il devrait séparer l'action requise de la révision recommandée. Il devrait expliquer ce que la plateforme a déjà fait et ce que le client seul peut vérifier. Si un utilisateur doit inspecter les journaux du fournisseur de code source, l'avis devrait indiquer la fenêtre de temps, le fournisseur et les types d'événements à vérifier. Si les builds automatisés échoueront jusqu'à la reconnexion, l'avis devrait expliquer que restaurer le build n'équivaut pas à terminer la révision de sécurité.

Les archives publiques montrent que l'avis de Docker mentionnait la reconnexion et les journaux de sécurité des fournisseurs de code source. C'est une force. Le manque restant est une preuve de clôture. Les lecteurs publics ne peuvent pas voir si Docker a ensuite confirmé l'absence d'abus de jetons, si chaque jeton concerné a été révoqué avec succès, si une population de clients a été oubliée, ou si un rapport final a atteint les clients. Une clôture privée a peut-être existé. Elle ne fait pas partie des archives publiques disponibles pour cet article. Cette incertitude devrait être enregistrée plutôt que comblée par des hypothèses.

Les journaux des fournisseurs de code source sont devenus la couche de preuve du client

L'avis de Docker a dit aux utilisateurs de vérifier les actions de sécurité GitHub ou Bitbucket pour des accès inattendus. Cette instruction était correcte, mais elle révèle également une limite de responsabilité. Docker pouvait révoquer les jetons et identifier les comptes Docker Hub concernés. La preuve de savoir si un dépôt de code source a été consulté ou modifié pouvait se trouver dans les journaux d'une autre entreprise et sous le compte du client. Cela transforme un incident de plateforme unique en une enquête inter-fournisseurs.

La page du journal de sécurité GitHub àhttps://docs.github.com/en/authentication/keeping-your-account-and-data-secure/reviewing-your-security-logexplique que les utilisateurs du compte peuvent examiner les actions les impliquant. La page de révision des applications OAuth GitHub àhttps://docs.github.com/en/apps/oauth-apps/using-oauth-apps/reviewing-your-authorized-oauth-appsdit aux utilisateurs de vérifier qu'aucune nouvelle application avec des permissions étendues n'est autorisée. Les conseils de restriction d'accès OAuth GitHub àhttps://docs.github.com/en/organizations/managing-oauth-access-to-your-organizations-data/about-oauth-app-access-restrictionsexpliquent comment les organisations peuvent contrôler l'accès des applications OAuth aux ressources de l'organisation. Ces contrôles sont centraux lorsqu'une intégration de build tierce est concernée.

La documentation OAuth de Bitbucket àhttps://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud/explique les flux de jetons et l'autorisation du fournisseur. Les conseils sur les journaux d'audit Bitbucket Cloud àhttps://support.atlassian.com/bitbucket-cloud/kb/bitbucket-cloud-audit-log-events/décrivent la journalisation au niveau de l'espace de travail. Les conseils de révocation de jetons Bitbucket àhttps://support.atlassian.com/bitbucket-cloud/docs/revoke-a-workspace-access-token/et la révocation de jetons de dépôt àhttps://support.atlassian.com/bitbucket-cloud/docs/revoke-a-repository-access-token/expliquent comment l'accès peut être supprimé. Ces documents montrent les preuves et le travail de réparation que les clients devaient coordonner en dehors de Docker.

Le défi de responsabilité est la corrélation. Un client doit connecter l'avis de compte concerné de Docker, la révocation des jetons de Docker, les journaux GitHub ou Bitbucket, les échecs de builds automatisés, l'activité du dépôt et l'historique de publication des images. Si le client ne peut pas corréler ces enregistrements, l'enquête se clôt par hypothèse. Cela peut être acceptable pour un projet amateur à faible risque. Ce n'est pas acceptable pour une chaîne de build d'entreprise ou une image open source largement consommée.

Le fournisseur pourrait réduire cette charge en fournissant des preuves structurées: identifiants de jetons concernés, type de fournisseur, noms de dépôts concernés si connus, heure de dernière utilisation si disponible, heure de révocation, action client requise et une déclaration claire sur la question de savoir si Docker a observé une utilisation des jetons pendant la période d'accès non autorisé. Les reportages publics ne montrent pas si chaque client a reçu ce niveau de détail en privé. Les archives publiques montrent que les utilisateurs ont été invités à vérifier les journaux et à reconnecter.

Les conseils modernes sur les jetons montrent ce que le chemin de réparation devrait devenir

Les conseils ultérieurs de Docker sur les jetons aident à définir à quoi devrait ressembler une réparation durable. La documentation sur les jetons d'accès personnels Docker àhttps://docs.docker.com/security/access-tokens/explique la génération, l'expiration, les permissions et la gestion des jetons. La documentation sur les jetons d'accès d'organisation Docker àhttps://docs.docker.com/enterprise/security/access-tokens/met l'accent sur les permissions de dépôt délimitées, les permissions de gestion, la rotation, la surveillance de l'utilisation des jetons et le stockage sécurisé. Le blog de Docker de 2019 sur les jetons d'accès personnels àhttps://www.docker.com/blog/docker-hub-new-personal-access-tokens/présentait les jetons comme un substitut aux mots de passe et un élément de base pour un contrôle d'accès avancé. Le blog de 2021 sur les jetons délimités de Docker àhttps://www.docker.com/blog/level-up-security-with-scoped-access-tokens/a rendu explicite la direction du moindre privilège.

Ces documents ultérieurs ne sont pas des preuves des contrôles existants en avril 2019. Ils sont pertinents car ils décrivent la logique de réparation durable pour la classe de risque. Les jetons devraient être délimités. Ils devraient expirer. Ils devraient être surveillés. Ils devraient être attribuables. Ils devraient être révocables. Ils ne devraient pas partager un large pouvoir d'administration entre des tâches non liées. Un jeton de build devrait faire seulement le travail nécessaire pour un build, et son utilisation devrait laisser suffisamment de preuves pour reconstruire l'activité.

La documentation de migration de Docker àhttps://docs.docker.com/docker-hub/repos/manage/builds/migrate/est également pertinente car elle indique que les builds automatisés Docker Hub sont dépréciés et seront retirés le 1er avril 2027. La page conseille de migrer vers des workflows CI, avec création de jetons et stockage sécurisé dans les gestionnaires de secrets des plateformes CI/CD. Cette direction future n'efface pas l'incident de 2019. Elle renforce le point que les identifiants de build automatisé hébergés par un registre sont une préoccupation de gouvernance particulière. Déplacer l'automatisation vers le CI/CD ne supprime pas le risque de jeton. Cela change qui stocke le jeton, qui journalise l'utilisation et qui peut prouver le build.

NIST SP 800-218 àhttps://csrc.nist.gov/pubs/sp/800/218/finalrecommande des pratiques de développement logiciel sécurisé qui peuvent être intégrées dans les cycles de vie du développement logiciel. Le formulaire d'attestation de développement logiciel sécurisé de la CISA àhttps://www.cisa.gov/resources-tools/resources/secure-software-development-attestation-formreflète la tendance du secteur public vers des pratiques de développement sécurisé fondées sur des preuves. L'OWASP CI/CD Security Cheat Sheet àhttps://cheatsheetseries.owasp.org/cheatsheets/CI_CD_Security_Cheat_Sheet.htmltraite les pipelines CI/CD comme des surfaces d'attaque de grande valeur. L'OWASP Secrets Management Cheat Sheet àhttps://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.htmlinsiste sur la centralisation, la rotation, l'audit et le contrôle du cycle de vie des secrets. Aucune de ces sources ne constitue des conclusions sur l'environnement privé de Docker. Elles définissent la norme de preuve qu'un système de jetons de chaîne de build moderne devrait satisfaire.

Le moindre privilège n'est utile que s'il est observable

Le moindre privilège est souvent décrit comme une discipline de définition des permissions, mais cet incident montre qu'il s'agit aussi d'une discipline de preuve. Un jeton avec des permissions étroites réduit les dégâts. Un jeton avec des permissions étroites et des journaux clairs réduit l'incertitude. Un jeton avec des permissions étroites, des journaux clairs, une expiration, un historique de rotation et une attribution au propriétaire donne à un répondant à incident un chemin vers la clôture. Sans cette preuve, un jeton révoqué peut laisser le client se demander si l'identifiant exposé importait avant la révocation.

Pour les builds automatisés Docker Hub, les questions utiles sont concrètes. Le jeton pouvait-il lire des dépôts privés? Pouvait-il écrire des clés de déploiement ou des webhooks? Pouvait-il modifier le contenu du dépôt? Pouvait-il déclencher des builds? Pouvait-il lire des secrets de build? Pouvait-il pousser des images? Était-il lié à un dépôt, une organisation ou l'accès large d'un utilisateur? A-t-il été utilisé depuis un emplacement réseau inattendu pendant la fenêtre d'exposition? Docker et le fournisseur de code source pouvaient-ils corréler les identifiants de jetons sans exposer les secrets?

Les archives publiques ne répondent pas à ces questions. Le modèle de contrôle durable devrait le faire.

Le moindre privilège observable change également le comportement du client. Si un client peut voir qu'un jeton était en lecture seule, limité à un dépôt, inutilisé pendant la fenêtre pertinente, révoqué à un moment précis et remplacé par un jeton délimité à durée de vie plus courte, le client peut prendre une décision délimitée. Il peut reconstruire des images à partir de commits connus et clore l'incident. Si le client ne peut rien voir de tout cela, il peut devoir supposer un rayon d'explosion plus large ou ne rien faire parce que la révision est trop coûteuse. Les deux résultats sont mauvais.

Les documents ultérieurs de Docker sur les jetons d'accès àhttps://docs.docker.com/security/access-tokens/ethttps://docs.docker.com/enterprise/security/access-tokens/pointent vers un modèle plus responsable car ils mettent l'accent sur les permissions, la gestion, la surveillance et le stockage sécurisé. La même idée apparaît dans les contrôles d'organisation GitHub et Bitbucket. Il ne suffit pas de donner aux utilisateurs un moyen de créer des jetons. Les plateformes devraient rendre la portée des jetons compréhensible avant la création, visible pendant l'utilisation et reconstructible après l'exposition.

Pour les écosystèmes CI/CD et de registre, le moindre privilège observable devrait devenir une attente contractuelle. Un fournisseur détenant des identifiants de build devrait être capable d'identifier la classe d'identifiant, la portée, le propriétaire, l'heure de création, la dernière utilisation, la protection de stockage, l'état de rotation et l'état de révocation. Un client devrait pouvoir exporter suffisamment de journaux pour enquêter sans dépendre uniquement des tickets de support. Les utilisateurs en aval devraient pouvoir épingler les digest d'image ou vérifier la provenance lorsque le workflow le permet.

Le résultat n'est pas une sécurité parfaite. C'est un champ d'incertitude plus petit et plus inspectable.

Les images conteneur portent la confiance en aval

L'incident importait car les conteneurs sont des artefacts en aval. Une image Docker peut être tirée par un ordinateur portable de développeur, un job CI, un cluster Kubernetes, un service cloud, un environnement de test ou un hôte de production. Elle peut être épinglée par tag, épinglée par digest, miroirée en interne, scannée, reconstruite ou tirée directement de Docker Hub. Si une exposition de jeton en amont soulève une incertitude sur l'intégrité de la source ou de l'image, le consommateur en aval peut ne pas savoir quelle hypothèse tester.

Les travaux académiques renforcent l'environnement de risque plus large. L'analyse de vulnérabilité de 2020 des images Docker Hub àhttps://arxiv.org/abs/2006.02932a étudié des milliers d'images et décrit Docker Hub comme un référentiel d'images majeur. L'étude de 2023 sur les secrets dans les images conteneur àhttps://arxiv.org/abs/2307.03958a constaté que les secrets exposés dans les images conteneur peuvent avoir un impact concret sur les certificats, les secrets API et les hôtes. Ces études ne prouvent rien sur l'incident de la base de données Docker Hub de 2019. Elles montrent pourquoi les registres d'images et les artefacts conteneur sont des surfaces à hautes conséquences pour les chaînes d'approvisionnement logicielles.

La différence clé est entre la compromission de plateforme et le risque créé par l'utilisateur. L'incident de 2019 concernait les données de compte et d'intégration de Docker Hub. Le problème des secrets dans les images concerne souvent des utilisateurs qui incorporent accidentellement des identifiants dans les images. Les deux risques se rencontrent au registre. La plateforme doit protéger les données de compte et de jeton. Les utilisateurs doivent éviter de publier des secrets et doivent vérifier la provenance des images. Les consommateurs en aval doivent décider quelles images ils approuvent.

Un écosystème de registre mature soutient ces trois rôles avec des contrôles et des preuves.

Pour Docker Hub, la question de responsabilité après l'exposition des jetons n'était pas seulement « les mots de passe ont-ils été réinitialisés? » C'était « un mainteneur peut-il prouver que le code source et la sortie d'image n'ont pas été modifiés pendant la fenêtre d'exposition? » Cette preuve peut nécessiter des journaux de dépôt, des journaux de build, des digest d'image, des tags signés, des vérifications de commits source, une révision des dépendances et des décisions de redéploiement en aval. Si les équipes ne peuvent pas produire cette preuve, elles peuvent devoir reconstruire et republier à partir de sources fiables.

Ce coût ne devrait pas être invisible. Le nombre direct dans l'avis public était d'environ 190 000 comptes. Le nombre indirect est inconnu à partir de preuves publiques: projets, images, systèmes CI et déploiements en aval touchés par ces comptes. Une petite population affectée en pourcentage de la plateforme peut encore si certains comptes maintiennent des images largement utilisées ou des builds d'entreprise privés.

Ce que les clients auraient dû pouvoir vérifier

Les clients devaient d'abord vérifier s'ils étaient concernés. Un bon avis devrait identifier si leur compte Docker Hub était concerné, si leur intégration de fournisseur de code source était concernée, quel fournisseur était concerné, si les jetons avaient été révoqués, si les builds automatisés échoueraient et quelles actions exactes étaient requises. Un message générique qui laisse les utilisateurs deviner peut provoquer une sous-réaction ou une panique. L'avis reproduit donnait des actions directes. L'inconnu est la quantité de détails spécifiques au compte que chaque utilisateur a reçue.

Deuxièmement, les clients devaient vérifier l'activité du fournisseur de code source. Pour GitHub, cela signifiait vérifier les journaux de sécurité, les applications OAuth, les événements d'audit de dépôt si disponibles, les clés de déploiement, les webhooks et les commits pendant la période pertinente. Pour Bitbucket, cela signifiait vérifier les journaux d'audit, les consommateurs OAuth, les jetons d'espace de travail ou de dépôt et les modifications de dépôt inattendues. Dans les deux cas, le but n'était pas seulement de voir si quelqu'un s'était connecté.

C'était de voir si un jeton lié aux builds automatisés avait créé ou modifié un accès, déclenché une activité inattendue ou touché du code.

Troisièmement, les clients devaient vérifier l'intégrité des images. Si un jeton avait une capacité d'écriture sur le code source ou la configuration de build, une image en aval pouvait être affectée même si le compte Docker Hub lui-même semblait normal. Les mainteneurs devraient comparer les commits source, les modifications de Dockerfile, les journaux de build, les digest d'image et les heures de publication. Si quoi que ce soit n'est pas clair, reconstruire à partir d'un commit connu avec de nouveaux identifiants et publier un avis clair pour les utilisateurs en aval.

Quatrièmement, les clients devaient vérifier l'hygiène des identifiants. La réinitialisation du mot de passe importe si les mots de passe hachés étaient concernés. Mais les jetons OAuth du fournisseur de code source, les jetons d'accès Docker Hub, les secrets CI/CD, les clés de déploiement, les secrets de webhook et les identifiants de registre ont tous des cycles de vie différents. L'OWASP Secrets Management Cheat Sheet àhttps://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.htmlest utile ici car il traite la gestion des secrets comme un stockage, un provisionnement, un audit, une rotation et un contrôle du cycle de vie, pas une réinitialisation ponctuelle.

Cinquièmement, les clients devaient vérifier la gouvernance future. Les restrictions d'accès OAuth des organisations GitHub àhttps://docs.github.com/en/organizations/managing-oauth-access-to-your-organizations-data/about-oauth-app-access-restrictionspeuvent empêcher l'accès non géré des applications OAuth. Les jetons d'accès d'organisation Docker àhttps://docs.docker.com/enterprise/security/access-tokens/peuvent être délimités aux dépôts et aux actions de gestion. Les permissions de jetons au niveau du dépôt Bitbucket àhttps://support.atlassian.com/bitbucket-cloud/docs/repository-level-access-token-permissions/peuvent limiter l'autorité des jetons. Ces contrôles réduisent le rayon d'explosion lors de la prochaine exposition d'intégration.

Ce qu'une réparation durable devrait prouver

Une réparation durable après un incident de jetons de registre de développement devrait prouver six choses. Premièrement, elle devrait prouver la portée. Le fournisseur devrait savoir quels comptes, classes de jetons, fournisseurs de code source et dépôts ont été concernés, et devrait distinguer l'exposition confirmée de l'exposition possible. Lorsque la preuve exacte n'est pas disponible, cette incertitude devrait être énoncée.

Deuxièmement, elle devrait prouver la révocation. L'invalidation des jetons doit être enregistrée avec l'heure, la cible, le fournisseur et l'état de réussite. Si la révocation échoue pour un fournisseur ou un client, l'exception doit être visible. « Nous avons révoqué les jetons » est utile, mais les clients doivent savoir si leur jeton a été révoqué et s'ils doivent prendre une mesure supplémentaire.

Troisièmement, elle devrait prouver l'analyse d'abus. Le fournisseur devrait conserver et analyser les preuves disponibles sur la question de savoir si les jetons exposés ont été utilisés pendant ou après l'accès non autorisé. Comme certaines preuves se trouvent chez les fournisseurs de code source, le fournisseur devrait donner aux clients suffisamment d'identifiants et de fenêtres de temps pour mener leur propre révision. Les archives publiques pour Docker Hub ne montrent pas une analyse d'abus complète. Cela reste une inconnue.

Quatrièmement, elle devrait prouver l'intégrité de la chaîne de build. Pour les plateformes de build automatisé, la récupération doit inclure les journaux de build, la corrélation des commits source, la révision des digest d'image, l'historique des tags et la réconciliation des builds échoués. Si les sorties d'image ne pouvaient pas être affectées parce que les jetons avaient une portée limitée, cela devrait être expliqué. Si les sorties d'image pouvaient avoir été affectées, les clients ont besoin d'un chemin de reconstruction et d'avis.

Cinquièmement, elle devrait prouver la communication avec le client. L'avis devrait séparer les faits confirmés, les actions du client, les actions du fournisseur, les inconnues, les prochaines mises à jour et les canaux de support. Il devrait également préciser que relier les fournisseurs de code source restaure la fonctionnalité mais ne remplace pas la révision des journaux de code source. L'avis Docker, tel que reproduit, listait des actions et pointait vers les journaux GitHub et Bitbucket. Un dossier public plus fort inclurait une déclaration de clôture finale.

Sixièmement, elle devrait prouver le futur moindre privilège. Le stockage des jetons devrait évoluer vers la délimitation, des durées de vie courtes, des comptes de service, des permissions par dépôt, la rotation, la surveillance et une gouvernance centralisée des secrets. La documentation ultérieure de Docker sur les jetons délimités et les jetons d'organisation reflète cette direction. La norme responsable n'est pas que chaque contrôle de 2019 correspondait déjà aux conseils futurs. C'est qu'un incident de jetons devrait produire un mouvement durable vers le moindre privilège et une utilisation vérifiable.

La responsabilité suit l'identifiant, pas seulement le compte

L'attribution finale devrait suivre le chemin de l'identifiant. Docker contrôlait la base de données Hub, l'environnement de stockage des jetons, la notification des utilisateurs et l'action de révocation des jetons. GitHub et Bitbucket contrôlaient l'autorisation du fournisseur de code source, les journaux et les mécanismes de révocation côté fournisseur. Les clients contrôlaient les dépôts, les définitions de build, les politiques d'organisation et les avis en aval.

Les utilisateurs et les déployeurs contrôlaient s'ils épinglaient les images, vérifiaient les digest, reconstruisaient à partir de la source ou continuaient à tirer des tags mutables.

Cette attribution est plus précise que de dire que Docker était responsable de tout ou que les clients étaient responsables de tout. Docker avait la meilleure vue de l'incident de base de données et de la population de jetons exposés. Les clients avaient la meilleure vue de l'activité du dépôt et de l'utilisation des images. Les fournisseurs de code source avaient la meilleure vue de l'activité des jetons dans leurs systèmes. Les utilisateurs en aval avaient le moins de visibilité et la plus grande dépendance aux preuves des mainteneurs. La chaîne ne fonctionne que si chaque partie peut produire la preuve qu'elle contrôle uniquement.

La responsabilité basée sur le chemin de l'identifiant change également la façon dont les incidents devraient être nommés. Appeler l'événement une brèche de compte est précis mais incomplet. L'appeler un incident de garde de jetons est plus utile car il dirige l'attention vers les ponts entre les systèmes. La même exposition de nom d'utilisateur et de mot de passe peut être contenue à l'intérieur d'une plateforme. Une exposition de jeton peut atteindre une autre plateforme par conception. Plus l'intégration est forte, plus la réponse doit voyager avec l'identifiant.

Pour les chaînes d'approvisionnement logicielles, cette leçon reste d'actualité même alors que les builds automatisés Docker Hub se dirigent vers la retraite. Les systèmes CI/CD, les registres de paquets, les référentiels d'artefacts, les déployeurs cloud, les hôtes de code source, les services de scan et l'automatisation de publication utilisent tous des identifiants pour connecter les services. Chaque intégration de commodité crée une question de garde. Où est stocké l'identifiant? Qui peut l'utiliser? Que peut-il toucher? Comment est-il révoqué? Quelles preuves prouvent qu'il n'a pas été abusé?

Un incident de registre en 2019 importe encore parce que ces questions ne sont devenues que plus centrales.

La norme responsable est donc simple mais exigeante: les identifiants exposés ne devraient pas laisser une incertitude silencieuse. La plateforme devrait révoquer et divulguer. Le fournisseur de code source devrait exposer les journaux et les contrôles. Le client devrait réviser et reconstruire si nécessaire. L'utilisateur en aval devrait avoir un moyen de vérifier les artefacts de confiance. Lorsqu'aucun maillon ne peut produire de preuve, la chaîne d'approvisionnement absorbe l'ambiguïté comme risque.

Le contre-factuel n'est pas l'absence d'incident; c'est l'absence de chemin silencieux dans la chaîne d'approvisionnement

Aucune grande plateforme de développement ne peut promettre qu'elle ne connaîtra jamais d'accès non autorisé. Le meilleur contre-factuel est qu'un incident ne peut pas passer silencieusement des données de compte au code source et aux artefacts conteneur. Si les jetons sont délimités, tournés, surveillés et révocables, la plateforme peut réduire le rayon d'explosion. Si les sorties de build sont traçables jusqu'aux commits source et aux digest d'image, les mainteneurs peuvent prouver l'intégrité. Si les avis aux clients sont spécifiques, les utilisateurs peuvent agir sans deviner.

L'incident Docker Hub de 2019 montre à quelle vitesse un problème de registre devient un problème de chaîne de contrôle. Docker contrôlait la base de données Hub, l'avis utilisateur, la révocation des jetons et l'intégration de build automatisé. GitHub et Bitbucket contrôlaient leurs journaux, les contrôles OAuth et les mécanismes de révocation de jetons. Les clients contrôlaient les dépôts de code source, la configuration de build, la publication d'images et la notification en aval. Les utilisateurs en aval contrôlaient les décisions de tirage, d'épinglage et de déploiement.

L'incident du registre a traversé toutes ces couches parce que les jetons d'intégration les reliaient.

Cette attribution ne soutient pas un blâme non étayé. Les archives publiques ne prouvent pas que les dépôts de code source de Docker Hub ont été modifiés ou que des images ont été compromises. Elles prouvent que la garde des jetons d'intégration de Docker a créé un devoir de responsabilité plus large qu'un événement de mot de passe normal. La bonne question n'est pas « chaque scénario du pire cas a-t-il été confirmé? » La bonne question est « quelles preuves ont fermé chaque scénario, et qui pouvait les voir? »

Pour les plateformes de développement, c'est la leçon permanente. Les fonctions de commodité deviennent des fonctions de responsabilité lorsqu'elles détiennent des identifiants. Les builds automatisés deviennent des surfaces de chaîne d'approvisionnement lorsqu'ils peuvent publier des artefacts. La confiance dans le registre devient une confiance dans les preuves lorsque les systèmes en aval déploient ce que le registre sert. Une réinitialisation de jeton n'est donc pas seulement une étape de récupération de compte.

C'est un test de la capacité de la chaîne d'approvisionnement logicielle à prouver que les identifiants, le code source, les builds, les images et la confiance en aval sont restés sous un contrôle responsable.