Pourquoi la CI
Pourquoi la sécurité de la chaîne d'approvisionnement a sa place dans votre CI
Le logiciel que vous livrez est ce que votre build CI a produit, à partir de ce qu'il a téléchargé à ce moment-là. Ce build est le seul endroit où vous pouvez voir ce qui est entré, décider ce qui a le droit d'entrer et enregistrer ce qui est entré dans la release.
Mis à jour le
What software supply chain security means
La définition de travail de la conférence : votre logiciel, c'est votre propre code plus tout ce dont il dépend, et la chaîne d'approvisionnement, c'est chaque étape qui amène ces éléments dans une version.
Petteri Pulkkinen et Erika Marttinen lors de Kubernetes Community Days Helsinki 2026, 2:35 à 4:28 de SBOMbastic: Getting Ready for Upcoming EU Cybersecurity Regulation in Software Supply Chains.
Votre build de production n'est pas celui de votre ordinateur portable
La plupart des équipes supposent que le code testé en local est le code livré. La source est la même, mais souvent pas le logiciel. Un build, c'est du code source plus tout ce qu'il récupère et tout ce qui l'entoure au moment de son exécution, et très peu de ces éléments sont figés.
Les dépendances non épinglées se résolvent différemment
Les plages de versions sont la norme. Dans npm, ^1.0.4 accepte toute release 1.x ultérieure : le même package.json installe donc des versions différentes selon les jours. Un lockfile les épingle, mais seulement s'il est commité et que le build le respecte : npm ci échoue lorsque le lockfile et package.json divergent, tandis que npm install peut mettre à jour le lockfile discrètement. Beaucoup de projets n'en commitent aucun. C'est le cas d'Express 5.2.1, un framework web largement utilisé.
Même une version épinglée n'est qu'un nom, pas un fichier. La documentation de pip explique que l'épinglage de version ne suffit pas à empêcher un index de paquets de servir des fichiers différents pour la même version, d'où son mode de vérification par hachage.
Le temps change les entrées
Les registres changent d'un build à l'autre. De nouvelles versions sont publiées, d'anciennes sont retirées, et une plage résolue sans risque lundi peut récupérer une release compromise mardi. Les tags de conteneur bougent aussi : la documentation de Docker prévient que les tags d'image sont mutables et qu'un éditeur peut modifier un tag pour le faire pointer vers une nouvelle image. FROM node:20 n'est donc pas la même image de base d'un mois à l'autre, sauf si vous l'épinglez par digest.
Le temps se retrouve aussi dans le résultat. Le projet Reproducible Builds voit dans les horodatages la principale source de problèmes de reproductibilité, car de très nombreux outils inscrivent la date et l'heure courantes dans ce qu'ils construisent.
L'environnement est différent
- Système d'exploitation et architecture. Un ordinateur portable sous macOS et ARM et un runner CI sous Linux et x86-64 installent des binaires précompilés différents pour le même paquet. De nombreux outils npm sont désormais livrés sous forme de paquets propres à une plateforme qui encapsulent un binaire compilé.
- Chaînes d'outils. Les versions du compilateur, du runtime et du gestionnaire de paquets dérivent d'une machine à l'autre, sauf si chacune est épinglée.
- Caches. Votre machine et votre CI restaurent des caches différents, construits à des moments différents à partir de résolutions différentes.
- Scripts d'installation et étapes de build. Les hooks post-installation, les actions de configuration et les scripts de build téléchargent des outils et des données au moment du build. Rien de cela n'apparaît dans un manifeste.
- Configuration. Les variables d'environnement, les flags de build et les secrets existent en CI et nulle part ailleurs.
Le projet Reproducible Builds définit un build reproductible comme un build où, à code source, environnement de build et instructions de build identiques, n'importe qui peut recréer des copies identiques bit à bit de tous les artefacts spécifiés. Cette définition montre tout ce qu'il faut maintenir constant. La plupart des équipes n'y parviennent pas avec leurs builds, et celles qui y parviennent ont beaucoup travaillé pour cela. D'ici là, le seul compte rendu fiable de ce qui a été livré est celui enregistré pendant l'exécution du build livré.
A software supply chain, walked end to end
Petteri Pulkkinen et Erika Marttinen lors de Kubernetes Community Days Helsinki 2026, 15:20 à 16:38 de SBOMbastic: Getting Ready for Upcoming EU Cybersecurity Regulation in Software Supply Chains.
Où vérifier, et ce que chaque endroit peut voir
Les contrôles de sécurité peuvent s'exécuter à quatre endroits. Chacun a son rôle, mais un seul voit le build qui a réellement produit votre release.
| Fonctionnalité | Dans le build CI | Poste du développeur | Scan du dépôt | Scan de l'artefact |
|---|---|---|---|---|
| Voit les versions réellement reçues par la production | Enregistrées lorsqu'elles sont récupérées | Une installation différente | Seulement si un lockfile les épingle | Ce qu'il peut reconnaître |
| Voit les paquets transitifs et restaurés depuis un cache | Son propre cache, pas celui de la CI | Lockfile uniquement | ||
| Voit ce que téléchargent les scripts d'installation | ||||
| Peut arrêter un appel sortant malveillant | Politique de trafic sortant sur le runner | |||
| Détecte les problèmes avant le push du code | Sur les pull requests |
- Inclus
- En partie
- Non inclus
Un scan du dépôt signale ce que le projet déclare. Un scan de l'artefact final signale ce qu'il peut y reconnaître. Aucun des deux n'a vu le build se dérouler. Express 5.2.1 ne commite aucun lockfile : un scanner pointé vers un checkout propre n'a donc aucune des dépendances npm du projet à résoudre et signale tout ce qu'il reconnaît par ailleurs. Pointez le même outil vers une copie installée du même dépôt, et un seul flag de cataloger change de nouveau la réponse. Le résultat dépend de ce qui a été installé avant le scan, c'est-à-dire précisément de ce qu'un scan ne contrôle pas. La page sur les SBOM au build explique pourquoi les scans divergent et ce que change l'enregistrement du build.
Le pipeline est une cible à part entière
La CI est le lieu où se rencontrent le code source, les dépendances et les secrets, ce qui en fait une cible de choix.
- tj-actions/changed-files (2025). Une GitHub Action largement utilisée a été compromise et a affiché des secrets CI dans les logs de build.
- Codecov Bash Uploader (2021). Un script modifié, exécuté dans la CI des clients, envoyait des variables d'environnement vers le serveur d'un attaquant.
- Le ver npm Shai-Hulud (2025). Des paquets compromis ont volé des identifiants à l'installation et s'en sont servis pour publier d'autres paquets compromis.
- xz utils (2024). Une porte dérobée a été cachée dans les archives de release et dans le processus de build lui-même, et non dans la source visible.
Chacune de ces attaques a exécuté du code pendant un build ou une installation. Un scan du dépôt exécuté avant, ou un scan de l'artefact exécuté après, n'aurait pas vu ce que faisait le processus de build. Les contrôles qui observent et limitent ce qu'un job peut atteindre doivent se trouver là où le job s'exécute. Cela vaut aussi pour les applications internes et discrètes : ces attaques visent le pipeline et les paquets que partagent toutes les applications, pas ce que fait une application. Voir la sécurité de la chaîne d'approvisionnement pour les logiciels internes et à faible risque.
Plus de code, plus de dépendances, moins de personnes pour les lire
Les agents de code IA écrivent et modifient le code plus vite que les équipes ne peuvent en relire chaque ligne, et ils ajoutent des dépendances au passage. Ils nomment aussi des paquets qui n'existent pas : une étude USENIX Security 2025 portant sur 576 000 échantillons de code généré a relevé des taux de paquets hallucinés d'au moins 5,2 % pour les modèles commerciaux et de 21,7 % pour les modèles open source. Un attaquant qui enregistre l'un de ces noms se fait installer par le prochain build qui lui fait confiance.
Chaque modification, quel que soit son auteur, humain ou non, passe par le build sur son chemin vers la production. Le build est donc le seul point de contrôle qui ne dépend pas du fait que quelqu'un ait regardé.
Les preuves doivent décrire ce qui a été livré
Les réglementations et les clients demandent des preuves, pas des intentions. Le Cyber Resilience Act de l'UE demande aux fabricants de recenser et de documenter les composants de leurs produits et d'en gérer les vulnérabilités pendant la période de support du produit. Une SBOM générée à partir d'un manifeste décrit ce que le projet a demandé. Une SBOM enregistrée à partir du build décrit ce qui est entré dans la release dont vous êtes responsable. Lorsqu'une nouvelle vulnérabilité est publiée, la seconde vous dit quelles releases sont touchées. Lisez ce qu'exige le CRA.
Ce que « dans la CI » devrait signifier
Exécuter un scanner comme étape CI est un début, mais il examine toujours des fichiers après leur arrivée. Bien fait, le contrôle dans la CI signifie :
- Enregistrer, ne pas déduire. Capturez chaque paquet et chaque téléchargement réellement récupérés par le job, y compris les dépendances transitives et tout ce qui est restauré depuis un cache.
- Indiquer la complétude de l'enregistrement. Une SBOM doit dire si elle couvre tout ce que le job a récupéré, et pas seulement lister ce qu'elle a trouvé.
- Contrôler le trafic sortant. Décidez quels hôtes un job peut atteindre et bloquez le reste avant qu'une dépendance compromise ne puisse contacter l'extérieur.
- Continuer à surveiller après la release. Revérifiez ce qui a été livré à mesure que de nouvelles vulnérabilités apparaissent, et transformez les résultats en corrections.
C'est ce que fait CRACI. C'est un runner pour vos jobs GitHub Actions : il enregistre ce que chaque build récupère, applique la politique de trafic sortant et surveille ce que vous avez livré. Migrer un workflow tient en une ligne : runs-on: craci. Voir comment fonctionne CRACI.
Ce que la CI ne remplace pas
Placer la sécurité de la chaîne d'approvisionnement dans le build ne rend pas les autres couches facultatives.
- Les postes des développeurs détiennent toujours des identifiants et exécutent des scripts d'installation. Protégez-les aussi : un ordinateur portable compromis peut pousser du code avant même qu'un build ne s'exécute.
- La revue de code et l'analyse statique trouvent des failles dans votre propre code, ce que ne fait pas un enregistrement des dépendances.
- L'épinglage, les lockfiles et les digests restent de bonnes pratiques. Ils réduisent l'écart entre les builds ; enregistrer le build vous dit de toute façon ce qui s'est passé.
Le build n'est pas le seul endroit où vérifier. C'est le seul endroit qui voit le logiciel que vous livrez réellement.
Découvrez CRACI sur votre propre pipeline
Réservez une démo et nous passerons en revue vos builds, vos SBOM et vos preuves de conformité.
Réserver une démo