Résumé

  • La compromission du Bash uploader de Codecov en 2021 est devenue un test de responsabilité des secrets CI car la mise à jour de sécurité de Codecov elle-même indiquait qu'un tiers avait modifié le Bash uploader et pouvait potentiellement exporter des variables d'environnement et des informations Git distantes des environnements CI des clients.
  • Le post-mortem de Codecov a ensuite déclaré que l'attaquant avait extrait une clé HMAC pour un compte de service Google Cloud Storage d'une couche intermédiaire dans une image Docker publique auto-hébergée et avait utilisé cette clé pour modifier le Bash uploader fourni aux utilisateurs finaux.
  • La question de responsabilité n'est pas simplement que les utilisateurs auraient dû vérifier les sommes de contrôle. Codecov contrôlait le chemin de distribution du chargeur, le processus de construction de l'image Docker publique, la surveillance du script hébergé, la notification des clients et le plan de migration hors du modèle de confiance curl-to-shell.
  • Les clients contrôlaient les secrets disponibles pour les jobs CI, la méthode de téléchargement utilisée, si la validation des sommes de contrôle était appliquée et la rapidité avec laquelle ils pouvaient faire pivoter les identifiants après notification. Ces contrôles clients n'effaçaient pas la responsabilité du fournisseur quant à l'intégrité du script.
  • Cet article considère la mise à jour de sécurité et le post-mortem de Codecov comme des sources primaires, les réponses des clients comme des preuves indirectes de première partie, et la documentation de NIST, CISA, SLSA, Sigstore et CI comme vocabulaire de contrôle technique. Il ne prétend pas avoir accès aux fichiers des forces de l'ordre, aux listes privées de clients ou aux journaux complets de l'infrastructure des attaquants.

Pourquoi ce cas appartient à un dossier de risque et de responsabilité

Codecov appartient à un dossier de risque et de responsabilité car la compromission du Bash uploader en 2021 a transformé une étape de téléchargement de couverture de routine en une voie possible d'exposition des secrets CI. La mise à jour de sécurité de Codecov du 15 avril 2021 surhttps://about.codecov.io/security-update/indiquait que Codecov avait appris le 1er avril que quelqu'un avait obtenu un accès non autorisé au script Bash uploader et l'avait modifié sans autorisation. L'entreprise a déclaré que l'acteur avait obtenu l'accès en raison d'une erreur dans le processus de création de l'image Docker de Codecov qui avait permis l'extraction d'un identifiant nécessaire pour modifier le chargeur. Codecov a indiqué qu'à partir du 31 janvier 2021, il y avait eu des altérations non autorisées périodiques qui pouvaient potentiellement exporter des informations stockées dans les environnements d'intégration continue des clients vers un serveur tiers en dehors de l'infrastructure de Codecov.

Ce compte rendu public rend l'affaire plus grande qu'un script de fournisseur compromis. Le Bash uploader s'exécutait dans les jobs CI des clients, souvent après la fin des tests et avant le téléchargement des données de couverture. Les jobs CI peuvent contenir des URL de dépôt, des métadonnées de construction, des jetons de déploiement, des identifiants de publication de paquets, des identifiants cloud, des clés de signature, des URL de bases de données, des secrets de webhook, des jetons d'accès personnels et des variables d'environnement utilisées par l'automatisation des tests et des versions.

Une petite addition malveillante à un chargeur peut devenir un point de collecte d'identifiants car les clients placent intentionnellement confiance et secrets dans le CI.

Le post-mortem de Codecov surhttps://about.codecov.io/apr-2021-post-mortem/a affiné l'histoire du contrôle. Il indiquait que l'acteur malveillant avait ciblé le Bash uploader et l'avait utilisé pour livrer une charge utile malveillante aux utilisateurs utilisant le Bash uploader, le Codecov GitHub Action, le Codecov CircleCI Orb et le Codecov Bitrise Step. Il indiquait que l'attaquant avait extrait une clé HMAC pour un compte de service Google Cloud Storage d'une couche intermédiaire dans une image Docker publique auto-hébergée de Codecov et avait utilisé cette clé pour modifier le Bash uploader dans Google Cloud Storage. Il indiquait également qu'un client avait détecté l'incident après avoir effectué une vérification SHASUM et avoir remarqué une discordance entre le hachage rapporté sur GitHub et le hachage calculé pour le chargeur téléchargé.

Ces faits placent la responsabilité dans un système partagé mais inégal. Codecov contrôlait le chargeur hébergé, le chemin d'écriture Google Cloud Storage, le processus de construction de l'image Docker auto-hébergée, la rotation des clés après incident, la notification des clients et la transition vers un nouveau chargeur. Les clients contrôlaient les variables CI présentes lors de l'exécution du chargeur, s'ils récupéraient le script en direct, si la validation des sommes de contrôle était effectuée et la rapidité avec laquelle ils pouvaient faire pivoter les secrets exposés.

Les fournisseurs CI contrôlaient des parties du masquage des secrets, de l'isolation des jobs et de la journalisation. Les utilisateurs en aval supportaient le risque si les identifiants exposés permettaient un accès ultérieur à des systèmes ou du code. La question pratique est de savoir si chaque partie disposait de suffisamment de preuves pour agir à temps.

L'événement s'inscrit dans l'économie des outils de développement car la proposition de valeur de Codecov était un rapport de couverture à faible friction sur de nombreux systèmes CI. Le dépôt archivé du Bash uploader de Codecov surhttps://github.com/codecov/codecov-bashmontre directement le modèle de commodité: les clients pouvaient récupérer et exécuter un script distant, utiliser le même chargeur sur de nombreux fournisseurs CI et éventuellement vérifier les SHASUMs. La commodité était le moteur de l'adoption. Mais lorsque le script distant de confiance est devenu modifiable à partir d'un chemin contrôlé par l'attaquant, le coût caché est apparu sous forme d'inventaire d'urgence des identifiants, de rotation, de révision des dépôts, de notification des clients et de réponse aux incidents.

Le Bash uploader a créé une inversion de confiance dans le CI

Les chargeurs de couverture sont faciles à sous-estimer. Ils apparaissent à la fin d'un job de test, après que le code principal de l'application a déjà été exécuté. Cet emplacement peut les faire paraître moins risqués que les outils de construction, les commandes de déploiement ou les étapes de publication de paquets. En réalité, un chargeur de couverture peut voir le même environnement que le job qui l'invoque, sauf si le pipeline l'isole délibérément. Si le job a des identifiants cloud, des jetons API, un accès aux dépôts, des secrets de registre de paquets ou des clés de service, le processus du chargeur peut être en mesure de les lire.

La propre documentation du Bash uploader de Codecov surhttps://docs.codecov.com/docs/about-the-codecov-bash-uploaderet les instructions du dépôt archivé montrent pourquoi cela importait. Le chargeur était conçu pour détecter les paramètres CI, rassembler les rapports et soumettre les données de couverture. Le même dépôt documentait un processus de vérification utilisant des fichiers SHASUM, mais le post-mortem de Codecov a reconnu que le processus n'avait pas été entièrement ou correctement documenté avant l'incident. La mise à jour de sécurité a également indiqué que les clients qui avaient effectué une comparaison des sommes de contrôle avant d'utiliser le Bash uploader pourraient ne pas être impactés. C'est une limite révélatrice: la vérification de l'intégrité était une défense valide, mais elle n'avait pas été rendue inévitable par le modèle de distribution.

L'inversion de confiance était simple. Les clients faisaient confiance au script de Codecov parce que le script était une dépendance dans un workflow qui mesurait la couverture des tests. Le script s'exécutait ensuite dans un environnement CI contrôlé par le client qui pouvait contenir beaucoup plus d'autorité que ce dont Codecov avait besoin pour recevoir un rapport de couverture. En effet, le client donnait à un outil de rapport une position à partir de laquelle il pouvait observer ou exporter des secrets de déploiement si l'outil était modifié. Cela ne signifie pas que chaque client a divulgué des secrets critiques.

Cela signifie que le rayon d'explosion dépendait de la conception de l'environnement CI de chaque client, et non seulement de la limite de service de Codecov.

L'avis officiel de Codecov listait les identifiants, jetons, clés, services, magasins de données, code d'application et informations Git distantes comme des classes qui pouvaient potentiellement être affectées si elles étaient accessibles lorsque le chargeur modifié s'exécutait. Cette déclaration doit être lue attentivement. Elle ne prouvait pas que chaque client avait perdu chaque secret. Elle décrivait le potentiel d'exposition basé sur l'endroit où le script s'exécutait.

Les clients devaient ensuite déterminer quels secrets étaient présents dans leurs propres jobs, si ces secrets étaient sensibles, quels systèmes ils déverrouillaient et si une utilisation ultérieure était visible dans les journaux.

La documentation moderne des CI renforce ce modèle de risque partagé. Les conseils de durcissement de GitHub Actions surhttps://docs.github.com/en/actions/security-guides/security-hardening-for-github-actionsdiscutent des secrets, des permissions de jetons, des actions tierces et des risques d'injection de script. La documentation des variables CI/CD de GitLab surhttps://docs.gitlab.com/ci/variables/et la documentation des variables d'environnement de CircleCI surhttps://circleci.com/docs/env-vars/montrent comment les systèmes CI exposent intentionnellement des secrets aux jobs sous conditions contrôlées. Ces documents ne sont pas des conclusions d'incidents concernant Codecov. Ils définissent l'environnement dans lequel la compromission de Codecov est devenue grave: les jobs CI sont des salles d'automatisation privilégiées, pas des terminaux neutres.

Le moment de la détection a fait porter l'incertitude aux clients

Le moment de la détection est une question centrale de responsabilité car les clients ne pouvaient pas connaître immédiatement l'étendue. Codecov a déclaré avoir appris le problème le 1er avril 2021 après qu'un client effectuant une validation SHASUM a signalé une discordance. La divulgation publique du 15 avril est intervenue après enquête, analyse médico-légale et coordination. La mise à jour de sécurité a indiqué que la fenêtre pertinente avait commencé le 31 janvier et que les utilisateurs concernés avaient été contactés par e-mail et notifications dans l'application.

La mise à jour du 29 avril a ajouté plus d'informations sur les variables d'environnement qui pouvaient avoir été obtenues sans autorisation et sur les organisations et dépôts impactés.

Il y a deux points d'équité à maintenir ensemble. Premièrement, la réponse aux incidents nécessite une enquête. Un fournisseur qui divulgue avant de comprendre les faits de base peut induire les clients en erreur et provoquer la mauvaise remédiation. Le post-mortem de Codecov a indiqué que l'entreprise a coordonné avec les forces de l'ordre fédérales et les agences de cybersécurité pendant l'enquête. Deuxièmement, les clients avec des secrets CI exposés ont leur propre horloge.

Si un identifiant cloud, un jeton de paquet, une clé de déploiement de dépôt ou une clé de signature était disponible pour un job en février, un client peut devoir le faire pivoter immédiatement, examiner les journaux d'audit et évaluer l'exposition en aval. Plus l'incertitude dure longtemps, plus il est difficile de savoir si l'identifiant a été utilisé.

Le dossier de responsabilité doit donc demander ce que les clients savaient le 1er avril, le 15 avril et le 29 avril. Savaient-ils quels dépôts utilisaient des chargeurs affectés? Savaient-ils s'ils avaient récupéré le chargeur en direct pendant les fenêtres compromises? Savaient-ils quelles variables d'environnement avaient été potentiellement obtenues? Savaient-ils quels secrets exacts étaient présents dans ces jobs? Savaient-ils si la validation des sommes de contrôle avait été effectuée? Disposaient-ils de journaux suffisamment longs pour inspecter une éventuelle utilisation abusive?

Ces questions déterminent si la notification était exploitable.

L'alerte de CISA pour Codecov surhttps://www.cisa.gov/news-events/alerts/2021/04/22/codecov-releases-security-updatea traité l'avis du fournisseur comme suffisamment important pour être amplifié. C'est une preuve publique utile que l'incident était une question de chaîne d'approvisionnement logicielle et de remédiation client, pas seulement un événement interne à Codecov. Le cadre de développement logiciel sécurisé de NIST surhttps://csrc.nist.gov/pubs/sp/800/218/finalest également utile ici car il cadre les composants logiciels tiers, les environnements de construction et la réponse aux vulnérabilités comme des contrôles du cycle de vie. La compromission de Codecov se situait à la frontière des trois.

L'histoire de la détection montre également la valeur et la faiblesse de la vérification côté client. Un client a découvert la discordance parce qu'il a vérifié le Bash uploader téléchargé par rapport au SHASUM attendu. C'est un signal fort que la vérification fonctionne. C'est aussi un contrôle faible si seuls des clients inhabituellement prudents l'effectuent. La conception plus forte est de rendre l'exécution non signée ou non vérifiable l'exception, pas la valeur par défaut. Le post-mortem de Codecov a indiqué que le nouveau chargeur serait livré comme un exécutable binaire signé et vérifiable par SHASUM et que la dépréciation du Bash uploader faisait partie de l'action corrective. L'annonce du nouveau chargeur surhttps://about.codecov.io/blog/introducing-codecovs-new-uploader/appartient au dossier de réparation pour cette raison.

La rotation des secrets était la véritable charge de travail des clients

Une fois la compromission rendue publique, la charge opérationnelle s'est rapidement déplacée vers les clients. Codecov a conseillé aux utilisateurs concernés d'identifier les clés et jetons exposés aux environnements CI, d'invalider les identifiants sensibles, de générer des remplacements et d'auditer l'utilisation des jetons. Cela semble simple jusqu'à ce qu'il soit appliqué à une organisation logicielle réelle.

Un seul job CI peut contenir des jetons de registre de paquets, des identifiants de fournisseur cloud, des clés de déploiement, des secrets de dépôt d'artefacts, des URL de bases de données pour les tests d'intégration, des mots de passe de comptes de test, des webhooks Slack ou PagerDuty, des mots de passe de registre Docker, des identifiants Terraform, du matériel de signature ou des jetons d'accès personnels. Ces secrets peuvent être réutilisés dans plusieurs dépôts ou hérités de paramètres CI au niveau de l'organisation.

Le défi côté client n'était pas seulement la rotation. C'était la cartographie. Quels dépôts utilisaient le chargeur affecté? Quels jobs ont été exécutés pendant les fenêtres affectées? Quelles variables d'environnement étaient présentes dans ces jobs? Les secrets étaient-ils masqués dans les journaux mais toujours lisibles par le processus? Quels comptes cloud, registres de paquets, hébergeurs de code et services internes acceptaient ces identifiants? Quels systèmes avaient des journaux d'audit? Combien de temps les journaux étaient-ils conservés?

L'organisation pouvait-elle prouver l'absence d'utilisation abusive, ou seulement faire pivoter de manière défensive? Le coût de l'incident se mesurait donc en travail de réponse aux incidents autant qu'en utilisation abusive confirmée.

Les réponses des clients de première partie montrent pourquoi cela importe. L'avis de sécurité public de HashiCorp surhttps://discuss.hashicorp.com/t/hcsec-2021-12-codecov-security-event-and-hashicorp-gpg-key-exposure/23512décrivait l'exposition d'une clé privée GPG utilisée pour signer les versions et un processus de révocation et de remplacement. La réponse de Twilio surhttps://www.twilio.com/en-us/blog/company/communications/response-to-the-codecov-vulnerabilitydécrivait son enquête et son évaluation de l'impact client. La réponse de Rapid7 surhttps://www.rapid7.com/blog/post/2021/05/13/rapid7s-response-to-codecov-incident/décrivait sa propre révision et remédiation. Le rapport d'incident de Mercari surhttps://about.mercari.com/en/press/news/articles/20210521_incident_report/décrivait l'exposition de données clients et employés liée à l'incident Codecov. Ce ne sont pas des preuves que chaque client de Codecov a eu le même résultat. Ce sont des preuves indirectes que la remédiation client était réelle, variée et conséquente.

L'exemple de HashiCorp est particulièrement instructif car les clés de signature ne sont pas des jetons API ordinaires. Une clé de signature peut affecter l'authenticité des logiciels. Son remplacement nécessite une révocation, une nouvelle distribution de confiance, une communication client et du temps. Cela ne signifie pas que Codecov a directement compromis chaque artefact signé. Cela signifie que l'exposition des secrets CI peut atteindre la chaîne d'approvisionnement logicielle si le matériel exposé comprend des clés utilisées pour attester ou distribuer des logiciels.

Le rayon d'explosion dépend du type de secret, de son utilisation, de sa durée de vie et des preuves de révocation.

L'exemple de Mercari illustre une autre limite. L'incident de Codecov était une compromission d'outil de fournisseur, mais l'exposition de données clients peut devenir visible dans l'environnement du client lui-même en fonction des secrets et systèmes disponibles pour les jobs CI affectés. C'est pourquoi la responsabilité du fournisseur et la responsabilité du client ne peuvent pas être séparées dans des cases distinctes. Codecov devait réparer l'intégrité du chargeur et dire aux clients ce qui s'était passé. Les clients devaient déterminer quels secrets étaient présents et ce que ces secrets pouvaient atteindre.

L'intégrité de la distribution était la principale revendication de réparation

La principale revendication de réparation après l'incident Codecov était l'intégrité de la distribution. Le modèle du Bash uploader encourageait les clients à récupérer du code exécutable au moment de l'exécution du job. Ce modèle facilitait les mises à jour et élargissait la prise en charge des langages, mais il faisait également du script hébergé une cible de grande valeur. Si un attaquant pouvait modifier le script dans le stockage, chaque récupération en aval non vérifiée pouvait hériter de la modification malveillante.

Le fournisseur devait donc montrer que les droits de modification, la signature, les sommes de contrôle, la surveillance, les constructions d'image et les procédures de publication avaient changé.

Le post-mortem de Codecov listait plusieurs actions correctives: révoquer la clé volée, auditer et faire pivoter les clés de production, mettre à jour les images Docker publiques pour utiliser des constructions squashees ou multi-étapes, lancer un nouveau chargeur, surveiller les actifs Google Cloud Storage pertinents, améliorer la documentation pour la validation des signatures et des SHASUMs, modifier la politique de génération et de rotation des clés, améliorer la réponse aux incidents et doter une fonction de sécurité dédiée. Chaque action répondait à un maillon différent de la chaîne.

La correction de l'image Docker répondait à la fuite de secrets via les couches d'image. La rotation des clés répondait au chemin d'identifiant immédiat. La surveillance répondait aux modifications non autorisées futures. Le nouveau chargeur répondait à la conception de distribution et de validation.

Les couches d'image Docker sont un point de preuve important. Codecov a déclaré que l'attaquant avait extrait une clé HMAC d'une couche intermédiaire dans une image Docker publique auto-hébergée. La propre documentation de Docker sur les constructions multi-étapes surhttps://docs.docker.com/build/building/multi-stage/explique pourquoi les artefacts de construction et le matériel intermédiaire doivent être exclus des images finales. L'action corrective du post-mortem de Codecov visant à squasher ou utiliser des constructions multi-étapes était donc directement liée à la classe de cause racine. Un secret dans une couche d'image n'est pas protégé simplement parce que le conteneur final semble propre.

Le vocabulaire plus large de la chaîne d'approvisionnement logicielle aide également. Le cadre SLSA surhttps://slsa.dev/et Sigstore surhttps://www.sigstore.dev/traitent tous deux de l'intégrité, de la provenance, de la signature et de la vérifiabilité des artefacts logiciels. Ils ne sont pas des tests de conformité rétroactifs pour le chargeur 2021 de Codecov. Ils définissent pourquoi un script hébergé modifiable est un modèle de distribution plus faible qu'un artefact signé, versionné, vérifiable avec provenance. OpenSSF Scorecard surhttps://scorecard.dev/cadre de même l'hygiène des dépendances et des dépôts comme des contrôles mesurables de la chaîne d'approvisionnement. Le point important n'est pas qu'un cadre aurait empêché chaque partie de l'incident. Le point est que l'intégrité des artefacts doit être conçue de sorte que les clients ne soient pas censés découvrir la falsification manuellement.

La documentation actuelle du chargeur Codecov surhttps://docs.codecov.com/docs/codecov-uploaderet le dépôt du chargeur surhttps://github.com/codecov/uploadermontrent la direction de migration loin de l'ancien modèle uniquement Bash. Le dépôt Codecov GitHub Action surhttps://github.com/codecov/codecov-actionreste pertinent car de nombreux utilisateurs consommaient Codecov via des intégrations de plateforme plutôt que par invocation directe de Bash. L'incident a montré que les wrappers, orbs et étapes peuvent hériter de la limite de confiance d'un chargeur sous-jacent partagé. Les clients peuvent penser qu'ils utilisent une intégration native CI, mais le risque peut toujours passer par le même script ou binaire distant.

Les fournisseurs CI et les clients devaient encore réduire le rayon d'explosion

La réparation du fournisseur était nécessaire, mais la réduction du rayon d'explosion côté client restait essentielle. Un environnement CI ne devrait pas exposer des secrets dont un job n'a pas besoin. Une étape de téléchargement de couverture a généralement besoin d'assez d'autorité pour lire les fichiers de couverture et s'authentifier auprès de Codecov. Elle ne devrait pas avoir besoin d'identifiants de déploiement cloud étendus, d'accès à la base de données de production, d'autorité de publication de paquets ou de jetons personnels à longue durée de vie, sauf si le même job combine des responsabilités non liées.

Le moindre privilège dans le CI n'est pas abstrait. Il détermine si une action ou un script tiers compromis voit un jeton de téléchargement inoffensif ou un identifiant à l'échelle de l'organisation.

GitHub Actions, GitLab CI, CircleCI, Buildkite, Jenkins et d'autres systèmes CI offrent aux organisations des moyens de limiter les variables, de séparer les jobs, de masquer les secrets, de restreindre l'accès aux branches, d'exiger des environnements protégés et de limiter les permissions des jetons. Mais ces contrôles ne sont utiles que si la conception du pipeline les utilise. Un job monolithique qui exécute des tests, construit des artefacts, déploie l'infrastructure, signe les versions, publie des paquets et télécharge la couverture crée une exposition en mode commun.

Si l'étape finale de couverture peut lire chaque variable d'environnement utilisée par les étapes précédentes, le rayon d'explosion est défini par la commodité plutôt que par le besoin.

L'événement Codecov appartient donc à la fois à l'automatisation de la sécurité et à l'économie des outils de développement. L'automatisation est censée réduire le risque manuel. Mais l'automatisation peut aussi cacher des hypothèses de confiance. Un fichier YAML peut avoir été copié des années plus tôt. Une commande de chargeur peut s'exécuter dans des dizaines de dépôts. Un secret au niveau de l'organisation peut être injecté dans chaque job parce que c'était plus facile que de le limiter par projet. Un jeton pivoté peut casser des pipelines si la propriété n'est pas claire.

L'incident a forcé les équipes à auditer une automatisation qui était devenue une infrastructure de fond.

Les preuves client devraient inclure un inventaire des secrets CI, une révision des permissions au niveau du job, un journal de rotation des jetons, une révision des journaux d'audit et une carte des dépendances pour les actions ou scripts tiers. Si une organisation ne peut pas répondre quels dépôts utilisaient un chargeur donné pendant une fenêtre définie, elle ne peut pas évaluer l'exposition en toute confiance. Si elle ne peut pas répondre quels secrets étaient présents, elle ne peut pas faire pivoter intelligemment.

Si elle ne peut pas dire si un jeton a été utilisé après l'exposition, elle ne peut pas séparer l'utilisation abusive confirmée de la rotation préventive.

C'est pourquoi les avis clients publics variaient. Certaines organisations n'ont signalé aucune preuve d'accès non autorisé après enquête. D'autres ont fait pivoter des clés ou divulgué une exposition plus concrète. Cette variation n'est pas contradictoire. Elle reflète le fait que le chargeur compromis de Codecov créait un mécanisme d'exfiltration potentiel, tandis que la conséquence en aval dépendait de chaque environnement CI. Le dossier de responsabilité doit garder l'exposition potentielle, l'accès confirmé aux secrets, l'utilisation abusive confirmée et l'impact sur les données client dans des catégories séparées.

Limites des preuves et discipline de non-surenchère

Les preuves publiques soutiennent une conclusion solide mais pas des affirmations illimitées.

Elles soutiennent que le Bash uploader de Codecov a été modifié sans autorisation, que la modification pouvait exporter des variables d'environnement et des informations Git distantes des environnements CI, que la fenêtre pertinente a commencé le 31 janvier et s'est terminée avec la remédiation le 1er avril 2021, qu'une discordance de somme de contrôle client a aidé à détecter le problème, qu'une couche d'image Docker publique a exposé un identifiant utilisé pour modifier le chargeur, et que Codecov a recommandé la rotation des identifiants pour les utilisateurs concernés.

Elles soutiennent que certains clients ont publiquement divulgué leur propre remédiation ou exposition.

Les preuves publiques ne soutiennent pas l'affirmation que chaque client de Codecov a divulgué des secrets sensibles, que chaque secret exposé a été utilisé, que chaque incident en aval a été causé par Codecov, ou que Codecov connaissait l'impact complet avant de divulguer. Elles ne révèlent pas la liste complète des clients affectés, les journaux complets de l'infrastructure des attaquants, toutes les conclusions des forces de l'ordre, tous les rapports médico-légaux ou chaque variable d'environnement client obtenue. Un dossier de responsabilité sérieux devrait nommer ces inconnues plutôt que de les remplir de suspicion.

La différence entre l'exposition potentielle et l'utilisation abusive confirmée est importante pour les clients et les utilisateurs en aval. La mise à jour de sécurité de Codecov parlait d'identifiants, jetons, clés, services, magasins de données, code d'application et informations Git distantes qui pouvaient potentiellement être affectés s'ils étaient disponibles pour le chargeur. Ce potentiel importait assez pour justifier des conseils de rotation larges. Mais le potentiel n'est pas la même chose que la preuve d'un accès ultérieur.

Les avis d'incident clients sont nécessaires parce que chaque client devait appliquer le chemin d'exposition général à son propre environnement.

Le moment de la divulgation est une autre limite. Codecov a divulgué publiquement le 15 avril après avoir découvert l'événement le 1er avril. L'entreprise a expliqué qu'elle enquêtait avec des experts médico-légaux et se coordonnait avec les autorités. Les clients peuvent toujours demander si un avertissement plus précoce ciblé était possible, si les clients à haut risque d'exposition auraient dû être notifiés plus tôt, et si les informations supplémentaires du 29 avril sont arrivées assez rapidement. Ce sont des questions de responsabilité légitimes. Ce ne sont pas des preuves de mauvaise foi sans plus de preuves.

L'article ne devrait pas non plus traiter la validation des sommes de contrôle comme un transfert complet de responsabilité. Codecov documentait la validation SHASUM et un client utilisant ce contrôle a détecté le problème. Ce fait ne signifie pas que chaque client était négligent s'il n'avait pas mis en œuvre la procédure facultative. Si le modèle d'utilisation courant du produit était de récupérer un script distant en direct, le fournisseur devait assumer le risque que de nombreux clients suivent le chemin facile.

Plus l'intégration est sans friction, plus le fournisseur a la responsabilité d'intégrer des contrôles d'intégrité dans le chemin par défaut.

Le test de responsabilité durable est la preuve d'une confiance réparée

Le test de responsabilité durable est de savoir si Codecov et ses clients ont converti l'incident en preuve d'une confiance réparée. Pour Codecov, la preuve signifiait révoquer la clé volée, faire pivoter les identifiants internes, supprimer les secrets de couche d'image exposés, changer les processus de construction d'image Docker, surveiller le stockage du script hébergé, documenter la validation, livrer un chargeur de remplacement signé et vérifiable, et améliorer la réponse aux incidents.

Pour les clients, la preuve signifiait identifier les dépôts affectés, énumérer les secrets CI, faire pivoter les identifiants exposés, examiner les journaux en aval, réduire les permissions des jobs et adopter la vérification pour les outils tiers.

La question clé de la réparation est la valeur par défaut de la distribution. Si les clients récupèrent et exécutent encore couramment du code modifiable sans vérification intégrée, la même classe de risque demeure. Si les chargeurs sont signés, versionnés, épinglés, vérifiés par somme de contrôle et surveillés, le risque est réduit. Si les jobs CI isolent le téléchargement de couverture de l'autorité de déploiement, une future compromission du chargeur aura moins à voler. Si les gestionnaires de secrets délivrent des identifiants à courte durée de vie au lieu de jetons à longue durée de vie, la rotation d'urgence devient plus facile.

Si les journaux d'audit sont conservés assez longtemps, les clients peuvent distinguer la précaution de l'utilisation abusive confirmée.

Les équipes d'approvisionnement et de gouvernance devraient également tirer des leçons de ce cas. Un outil de développement qui s'exécute dans le CI n'est pas un module complémentaire d'observabilité inoffensif. C'est une exécution de code dans un environnement d'automatisation qui peut contenir des secrets de grande valeur.

Les examens des fournisseurs devraient demander comment les chargeurs et actions sont distribués, si les artefacts sont signés, comment la compromission est détectée, comment les clients sont notifiés, quelles télémétries le fournisseur peut fournir pour identifier les dépôts affectés, et comment le fournisseur évite de stocker ou d'exposer les clés de signature dans des artefacts de construction publics.

L'incident a également changé le sens de « l'automatisation de la sécurité ». L'automatisation n'est pas sécurisée parce qu'elle est automatisée. Elle est sécurisée lorsque l'automatisation a une autorité limitée, des entrées vérifiables, des artefacts reproductibles, des journaux audités et une révocation rapide. La compromission du Bash uploader de Codecov a montré qu'une petite étape d'automatisation peut devenir une grande limite de confiance si elle s'exécute là où résident les secrets.

La leçon finale est pratique. Les données de couverture comptent, mais le téléchargement de couverture ne devrait pas partager une pièce avec chaque identifiant qu'une entreprise possède. Un fournisseur de télémétrie développeur doit prouver l'intégrité du code qu'il demande aux clients d'exécuter. Les clients doivent concevoir le CI de sorte que les outils tiers voient seulement ce dont ils ont besoin. Lorsque l'une ou l'autre partie se fie à la commodité sans preuve, la facture arrive sous forme de rotation d'urgence des secrets, de notification client et d'incertitude sur la chaîne d'approvisionnement.

Codecov a rendu cette facture visible.

Le chargeur était petit, mais son contexte d'exécution était grand

Une raison pour laquelle l'incident Codecov reste important est que l'objet compromis était opérationnellement petit. Ce n'était pas un hôte de code source complet, une console cloud, un fournisseur d'identité ou un registre de paquets. C'était un chargeur de couverture. Mais le contexte d'exécution du chargeur pouvait être grand car les jobs CI rassemblent fréquemment l'autorité de nombreux systèmes à la fois.

Un job de test peut cloner un dépôt privé, télécharger des dépendances, accéder à des miroirs de paquets internes, décrypter des identifiants de test, démarrer des services cloud, publier des rapports, s'authentifier auprès d'une plateforme de couverture et déclencher des étapes de déploiement ultérieures. Si les mêmes variables d'environnement sont visibles dans tout ce job, un script de rapport final hérite d'un accès créé à d'autres fins.

C'est pourquoi le moindre privilège dans le CI doit être implémenté au niveau du job et de l'étape, pas seulement au niveau de l'organisation. Un secret approprié pour le déploiement ne devrait pas être injecté dans un job de couverture uniquement. Un jeton de publication de paquet ne devrait pas être disponible lors d'une étape de test unitaire qui télécharge la couverture. Un identifiant cloud utilisé pour les tests d'intégration devrait être à courte durée de vie et limité aux ressources de test. Les jetons de dépôt devraient avoir des permissions minimales.

Les secrets de branches protégées ne devraient pas être exposés à des contextes de pull request non fiables. La compromission de Codecov n'a pas inventé ces règles, mais elle a fourni une raison concrète de les appliquer.

L'incident montre également pourquoi le masquage des secrets ne suffit pas. Les plateformes CI masquent souvent les secrets dans les journaux, ce qui est utile, mais le masquage n'empêche pas un processus de lire une variable d'environnement et de l'envoyer ailleurs. Le masquage protège les lecteurs humains des journaux. Il ne convertit pas un secret de haute autorité en un secret de faible autorité. Si un script tiers s'exécute dans le même contexte de processus que le secret, le contrôle est déjà passé de la confidentialité dans les journaux à la confiance dans le code. C'est une hypothèse beaucoup plus forte.

Une conception plus forte sépare le téléchargement de couverture dans une étape contrainte. L'étape reçoit uniquement les fichiers de couverture et le jeton nécessaire pour s'authentifier auprès du service de couverture. Elle exécute une version épinglée du chargeur ou un binaire signé vérifié. Elle n'a pas d'identifiants de déploiement, de clés cloud de production, de jetons de publication de paquets, de jetons d'accès personnels à longue durée de vie ni d'accès aux sorties de jobs non liées. Si le chargeur est ultérieurement compromis, l'attaquant voit un environnement restreint.

L'incident devient un problème d'intégrité du fournisseur plutôt qu'un événement de rotation de secrets à l'échelle de l'entreprise.

Cette conception aide également l'enquête. Lorsqu'un outil tiers compromis a un environnement restreint, les répondants peuvent répondre rapidement aux questions d'exposition. Ils savent quel jeton était présent, quel système il atteignait, s'il a été pivoté et quels journaux vérifier. Lorsqu'un job a de nombreux secrets hérités, les répondants doivent reconstruire un graphe large sous pression temporelle. Le coût opérationnel de l'incident Codecov provenait en partie de cette incertitude. Les clients devaient découvrir ce que leurs propres jobs CI avaient rendu visible.

La vérification devrait être par défaut, observable et ennuyeuse

Le dossier Codecov illustre également un principe plus large: la vérification logicielle doit être par défaut, observable et ennuyeuse. Elle ne devrait pas dépendre d'un client inhabituellement prudent remarquant une discordance de hachage. Le client qui a trouvé la discordance a rendu un service public important, mais un canal de distribution mature devrait rendre la falsification visible à chaque consommateur ou arrêter l'exécution automatiquement.

Cela signifie des versions épinglées, des artefacts signés, une publication indépendante des sommes de contrôle, des constructions reproductibles ou auditées lorsque c'est possible, une surveillance des modifications inattendues d'objets et une documentation claire que les équipes ordinaires peuvent suivre sans devenir des spécialistes de la chaîne d'approvisionnement.

Il y a un équilibre pratique. Les outils de développement réussissent parce qu'ils sont faciles à adopter. Si la vérification est trop difficile, les équipes la sauteront. Si la vérification est facultative et enterrée, seules les équipes les plus soucieuses de la sécurité l'utiliseront. Le fournisseur doit donc concevoir l'intégration par défaut de sorte que le chemin sûr soit le chemin normal. Une action GitHub devrait épingler les versions et les permissions clairement. Un chargeur binaire devrait être signé et vérifié par les instructions d'installation.

Un orb ou une étape CI ne devrait pas envelopper silencieusement un script distant modifiable sans rendre cette dépendance visible. La documentation devrait expliquer les modes d'échec, pas seulement les commandes du chemin heureux.

L'observabilité compte du côté du fournisseur également. Le post-mortem de Codecov a indiqué qu'il avait ajouté une surveillance pour les actifs Google Cloud Storage pertinents. Cette catégorie de contrôle est essentielle. Un bucket de distribution de script ou de binaire hébergé devrait produire des alertes lorsque le contenu change de manière inattendue, lorsque des clés sont utilisées dans des contextes inhabituels, lorsque les métadonnées des objets changent ou lorsque les chemins de version divergent de l'automatisation attendue. La signature protège les clients au moment de l'exécution.

La surveillance protège le fournisseur au moment de la distribution. Les deux sont nécessaires.

Enfin, les preuves de vérification devraient survivre à un incident. Après une compromission, les clients ont besoin de savoir quelles versions d'artefact existaient, quand elles ont changé, quelles signatures étaient valides, quels chemins d'intégration ont récupéré quel artefact et quels dépôts ont été exécutés pendant la période affectée. Un fournisseur qui ne peut pas répondre à ces questions laisse les clients déduire l'exposition à partir de journaux qui peuvent être incomplets. La meilleure réparation après Codecov n'est pas seulement un chargeur plus sûr.

C'est un registre de preuves de distribution qui permet aux clients de limiter rapidement les incidents futurs.

Ce registre est le pont entre la responsabilité du fournisseur et l'action du client. Codecov peut rendre l'intégrité du chargeur vérifiable. Les clients peuvent réduire les secrets CI et épingler les dépendances. Les plateformes CI peuvent prendre en charge les limites de permissions, la délimitation des secrets et les journaux d'audit. Aucun de ces contrôles seuls n'est suffisant. Ensemble, ils transforment une étape de téléchargement de couverture d'une hypothèse de confiance cachée en une limite d'automatisation contrôlée.

L'approvisionnement devrait traiter les outils CI comme du code privilégié

La leçon d'approvisionnement est directe: tout outil qui s'exécute dans le CI devrait être examiné comme du code privilégié, même si la fonction métier semble observationnelle. Les rapports de couverture, l'analyse statique, l'analyse des dépendances, le téléchargement d'artefacts, la génération de notes de version, la publication de documentation et les notifications de déploiement peuvent tous s'exécuter dans des environnements qui détiennent des secrets.

Un questionnaire fournisseur qui demande seulement si le service stocke des données client manque la question la plus importante: quel code le fournisseur demande-t-il au client d'exécuter, d'où vient ce code, comment est-il vérifié et quelle autorité peut-il observer pendant l'exécution?

Un examen utile demanderait si le fournisseur publie des versions signées, si les clients peuvent épingler des versions immuables, si les scripts hébergés sont surveillés pour des modifications inattendues, si les clés de distribution sont isolées des artefacts de construction publics, si les avis d'incident peuvent identifier les chemins d'intégration affectés et si le fournisseur peut fournir suffisamment de télémétrie pour que les clients puissent évaluer l'exposition. Il demanderait également si le client a séparé les étapes CI de sorte que l'outil du fournisseur reçoive uniquement les permissions nécessaires.

La réponse est en partie contractuelle, en partie architecturale et en partie opérationnelle.

L'examen devrait également traiter le support en cas d'incident comme faisant partie du produit. Lorsqu'un fournisseur intégré au CI divulgue une compromission, les clients ont besoin de plus qu'un article de blog général. Ils ont besoin des hachages des artefacts, des fenêtres temporelles affectées, des noms d'intégration, de la méthode de détection, de l'ordre de rotation recommandé, des hypothèses fausses connues et d'un moyen de demander si leurs propres dépôts ou jetons ont été observés.

Un fournisseur peut ne pas être en mesure de divulguer tous les détails médico-légaux, surtout pendant que les forces de l'ordre ou les enquêtes clients sont actives, mais il peut préparer un package de réponse qui permet aux clients d'agir rapidement. L'incident Codecov a montré que la charge opérationnelle d'un outil développeur compromis atterrit à l'intérieur de centaines ou milliers de pipelines clients, pas seulement au sein de l'équipe de sécurité du fournisseur.

Ce package de support devrait être testé avant un incident. Un fournisseur devrait savoir quels systèmes orientés client peuvent envoyer des avis urgents, quelles pages de documentation hébergeront les conseils de rotation, quelles files d'attente de support trieront les environnements à haut risque et quels journaux peuvent aider les clients à identifier si une intégration a été exécutée pendant la fenêtre affectée. Sans cette préparation, la divulgation devient un deuxième mode de défaillance: le fournisseur peut découvrir l'incident technique, mais les clients perdent encore du temps à reconstruire la carte d'exposition pratique.

La responsabilité inclut donc non seulement la prévention de la falsification du chargeur, mais aussi la rendation de la première heure de réponse du client utilisable.

Ce cas n'est donc pas seulement une note historique sur un script Bash compromis. C'est un modèle pour juger les outils de développement qui résident dans l'automatisation. La question sûre n'est plus « faisons-nous confiance à ce fournisseur? » dans l'abstrait. La question sûre est « que pourrait lire ce code contrôlé par le fournisseur s'il changeait demain, et quelles preuves nous montreraient cela rapidement? ». L'incident de Codecov a rendu cette question visible pour chaque équipe qui avait laissé un script de commodité s'exécuter à côté de secrets de qualité production.