Sécuriser une pipeline CI/CD
Mise à jour :
Pourquoi sécuriser une pipeline ?
Une pipeline CI/CD (Continuous Integration / Continuous Delivery) est le système automatisé qui teste, compile et déploie votre code. C’est un moteur d’exécution qui a accès à tout ce qui compte :
- Vos secrets (mots de passe, clés API, tokens d’accès)
- Votre code source (tout ce que vous développez)
- Vos environnements de production (là où tournent vos applications)
L’analogie : Imaginez que votre pipeline soit un employé avec un trousseau de clés qui ouvre toutes les portes de l’entreprise. Si quelqu’un vole ce trousseau ou manipule cet employé, il a accès à tout.
Ce guide présente un modèle conceptuel pour sécuriser une pipeline. L’objectif n’est pas de lister des outils — c’est de comprendre les surfaces de contrôle sur lesquelles agir, quel que soit l’outil que vous utilisez.
La pipeline comme surface d’attaque
Ce qu’un attaquant peut obtenir
Une pipeline compromise offre un accès privilégié à plusieurs ressources critiques :
| Ressource | Ce que l’attaquant peut faire | Exemple concret |
|---|---|---|
| Secrets | Voler les tokens d’API, clés SSH, credentials cloud | Accéder à votre compte AWS avec vos propres clés |
| Code source | Modifier le code avant compilation | Ajouter une backdoor invisible |
| Artefacts | Injecter du malware dans les livrables | Vos utilisateurs téléchargent une version infectée |
| Production | Déployer du code malveillant directement | Prendre le contrôle de vos serveurs |
Les quatre piliers de la sécurité
La sécurité d’une pipeline repose sur quatre piliers. Chaque pilier représente une décision de confiance qui doit être explicite et vérifiable :
| Pilier | Question clé | Risque si négligé |
|---|---|---|
| Identités | Qui a le droit de faire quoi ? | Accès excessifs, secrets volés |
| Dépendances | À quel code externe faisons-nous confiance ? | Code malveillant exécuté |
| Runners | Où s’exécute le code ? | Contamination entre jobs |
| Artefacts | Comment prouver l’origine du livrable ? | Distribution de malware |
Pilier 1 : Identités et permissions
Le problème expliqué simplement
Votre pipeline doit s’authentifier auprès de nombreux services : registres de conteneurs (pour stocker vos images), clouds (AWS, Azure, GCP), outils de déploiement. Ces authentifications reposent sur des secrets — des identifiants qui prouvent qui vous êtes.
L’analogie : C’est comme avoir des badges d’accès pour différentes zones d’un bâtiment. Si vous perdez un badge “accès total”, le voleur peut aller partout. Si vous n’avez qu’un badge “visiteur”, les dégâts sont limités.
Les bonnes pratiques
1. Principe du moindre privilège
Chaque job n’a que les permissions strictement nécessaires. Pas plus.
# ❌ Permissions excessives — donne tous les droitspermissions: write-all# Problème : si ce job est compromis, l'attaquant peut tout faire
# ✓ Permissions minimales — seulement ce qui est nécessairepermissions: contents: read # peut lire le code, mais pas le modifier packages: write # peut publier des packages, rien d'autre2. Tokens éphémères plutôt que secrets permanents
Un token éphémère expire automatiquement après quelques minutes. Un secret statique reste valide indéfiniment (jusqu’à révocation manuelle).
| Caractéristique | Secret statique | Token éphémère (OIDC) |
|---|---|---|
| Durée de vie | Illimitée | Quelques minutes |
| Si volé | Utilisable jusqu’à détection | Expire rapidement |
| Révocation | Manuelle, souvent oubliée | Automatique |
OIDC (OpenID Connect) est un protocole qui permet d’obtenir des tokens éphémères. Au lieu de stocker un secret permanent, la pipeline demande un token temporaire à chaque exécution.
3. Séparation par environnement
Les secrets de staging (environnement de test) doivent être différents des secrets de production. Ainsi, si un secret de développement fuite, la production reste protégée.
Questions à vous poser
Avant de configurer les accès d’un job, demandez-vous :
- Ce token a-t-il besoin d’écrire, ou seulement de lire ?
- Peut-on utiliser OIDC au lieu d’un secret statique ?
- Que se passe-t-il si ce secret est volé ?
- Quand ce secret a-t-il été renouvelé pour la dernière fois ?
Pilier 2 : Dépendances
Le problème expliqué simplement
Chaque npm install, chaque pip install, chaque action GitHub tierce est du
code qui s’exécute avec les permissions de votre pipeline. Ce code provient
de mainteneurs que vous ne connaissez pas.
L’analogie : C’est comme inviter des inconnus chez vous et leur donner vos clés. La plupart sont honnêtes, mais il suffit d’un seul malveillant pour que tout soit compromis.
Les bonnes pratiques
1. Épingler par hash (pas par tag)
Un tag comme @v4 ou @latest est mutable — le mainteneur peut le
modifier à tout moment. Un hash SHA est immuable — c’est l’empreinte
unique d’une version précise du code.
# ❌ Tag mutable — peut changer sans prévenir- uses: actions/checkout@v4# Risque : demain, @v4 pourrait pointer vers du code différent
# ✓ Hash immuable — toujours le même code- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683# Garantie : ce hash correspond toujours exactement au même code2. Commiter les lockfiles
Un lockfile (comme package-lock.json ou poetry.lock) enregistre les
versions exactes de toutes vos dépendances.
| Sans lockfile | Avec lockfile |
|---|---|
npm install télécharge les dernières versions | npm ci installe exactement les versions enregistrées |
| Résultat différent à chaque exécution | Résultat identique à chaque exécution |
| Une mise à jour peut casser le build | Mises à jour contrôlées et testées |
3. Auditer avant d’ajouter
Avant d’ajouter une nouvelle dépendance, vérifiez :
| Critère | Pourquoi c’est important |
|---|---|
| Qui la maintient ? | Un mainteneur unique est un risque (bus factor) |
| Depuis combien de temps ? | Une dépendance récente n’a pas fait ses preuves |
| Combien de téléchargements ? | Peu de téléchargements = peu d’yeux pour détecter les problèmes |
| Le code est-il lisible ? | Du code obfusqué cache peut-être quelque chose |
Questions à vous poser
- Cette dépendance est-elle vraiment nécessaire ?
- Avons-nous vérifié son code source ?
- Que se passe-t-il si le mainteneur perd l’accès à son compte ?
- Avons-nous un plan si cette dépendance disparaît ?
Pilier 3 : Runners et isolation
Le problème expliqué simplement
Un runner, c’est la machine (physique ou virtuelle) qui exécute votre pipeline. Cette machine exécute du code potentiellement dangereux : tests, builds, scripts. Si l’isolation est insuffisante, un job compromis peut contaminer les suivants.
L’analogie : Imaginez une cuisine partagée. Si quelqu’un prépare un plat contaminé et ne nettoie pas après lui, le cuisinier suivant utilise des ustensiles sales. Un runner persistant, c’est une cuisine qui n’est jamais nettoyée entre les services.
Les bonnes pratiques
1. Runners éphémères
Un runner éphémère est créé pour un job, puis détruit. Aucun état ne persiste entre les exécutions.
| Runner persistant | Runner éphémère |
|---|---|
| Job 1 modifie des fichiers | Job 1 s’exécute, runner détruit |
| Job 2 hérite de ces modifications | Job 2 obtient un runner neuf |
| Un malware peut persister | Impossible de persister quoi que ce soit |
2. Isolation réseau
Le runner ne doit accéder qu’aux ressources strictement nécessaires. Pas d’accès au réseau interne par défaut.
3. Séparation des contextes (forks et PRs externes)
Quand quelqu’un extérieur à votre organisation ouvre une Pull Request, le code qu’il propose s’exécute sur vos runners. Ce code ne doit jamais avoir accès à vos secrets.
Questions à vous poser
- Le runner est-il détruit après chaque job ?
- Que peut voir un job malveillant exécuté sur ce runner ?
- Les forks ont-ils accès aux mêmes ressources que les branches internes ?
- Comment détecterait-on une compromission du runner ?
Pilier 4 : Artefacts et chaîne de confiance
Le problème expliqué simplement
Un artefact, c’est le résultat de votre pipeline : une image Docker, un fichier exécutable, un package npm. C’est ce que vos utilisateurs téléchargent et exécutent.
Si la pipeline est compromise, l’artefact l’est aussi. Comment prouver qu’un artefact est légitime et n’a pas été modifié ?
L’analogie : C’est comme un scellé sur un médicament. Sans le scellé, impossible de savoir si quelqu’un a ouvert la boîte et modifié le contenu. La signature cryptographique est le “scellé numérique” de vos artefacts.
Les bonnes pratiques
1. Signature cryptographique
Signer un artefact, c’est y apposer une empreinte numérique qui prouve son origine. Si l’artefact est modifié après signature, la vérification échoue.
| Artefact non signé | Artefact signé |
|---|---|
| Origine inconnue | Origine vérifiable |
| Intégrité incertaine | Intégrité garantie |
| ”Faites-moi confiance" | "Vérifiez vous-même” |
2. Attestations de provenance
Une attestation est un document qui décrit comment l’artefact a été construit :
- Quel commit a produit cet artefact ?
- Quelle pipeline l’a construit ?
- Dans quel environnement ?
- Avec quelles dépendances ?
3. SBOM (Software Bill of Materials)
Un SBOM, c’est la liste complète de tous les composants inclus dans votre artefact. C’est comme la liste des ingrédients sur un emballage alimentaire.
Pourquoi c’est utile : Quand une vulnérabilité est découverte (ex: Log4Shell), vous savez en quelques secondes si vos artefacts sont concernés.
Artefact complet │ ├── Signature (qui a signé → preuve d'origine) ├── Attestation (comment c'est construit → traçabilité) └── SBOM (ce qu'il contient → inventaire)Questions à vous poser
- Nos artefacts sont-ils signés ?
- Peut-on vérifier leur provenance ?
- Avons-nous un inventaire de ce qu’ils contiennent (SBOM) ?
- Qui peut publier des artefacts dans notre registre ?
Contrôles structurels vs contrôles ponctuels
Il existe deux types de contrôles de sécurité, et ils ne se valent pas.
Contrôles ponctuels
Ce sont des vérifications exécutées à un moment précis :
- Scan de vulnérabilités avant déploiement
- Analyse statique du code
- Tests de sécurité sur une Pull Request
Le problème : un contrôle ponctuel peut être contourné, désactivé, ou simplement oublié.
Contrôles structurels
Ce sont des contraintes architecturales impossibles à contourner :
| Contrôle structurel | Pourquoi c’est plus solide |
|---|---|
| Permissions minimales par défaut | Impossible d’avoir plus de droits que prévu |
| Runners éphémères | Impossible de persister un malware |
| Signature obligatoire pour déployer | Impossible de déployer un artefact non vérifié |
| OIDC au lieu de secrets statiques | Impossible de voler un token permanent |
L’analogie : Un contrôle ponctuel, c’est un vigile qui vérifie les badges. Un contrôle structurel, c’est une porte qui ne s’ouvre physiquement qu’avec le bon badge. Le vigile peut être distrait ; la porte, non.
Modèle de maturité
Évaluez où vous en êtes et progressez étape par étape :
Niveau 1 : Hygiène de base
Les fondamentaux, à mettre en place en priorité :
- Permissions minimales sur chaque job
- Lockfiles committés et utilisés (
npm ciplutôt quenpm install) - Aucun secret en dur dans le code
Niveau 2 : Épinglage et isolation
Renforcement des contrôles :
- Dépendances et actions épinglées par hash SHA
- Runners éphémères (détruits après chaque job)
- Secrets différents par environnement (dev ≠ prod)
Niveau 3 : Vérification et traçabilité
Capacité à prouver et auditer :
- Artefacts signés cryptographiquement
- SBOM généré à chaque build
- Attestations de provenance
Niveau 4 : Confiance zéro
Sécurité maximale :
- OIDC au lieu de secrets statiques partout où c’est possible
- Politique de vérification obligatoire avant tout déploiement
- Monitoring des comportements anormaux sur les runners
À retenir
- Une pipeline compromise donne accès à vos secrets, votre code, et votre production
- Les quatre piliers sont : identités, dépendances, runners, artefacts
- Moindre privilège : chaque job n’a que les permissions strictement nécessaires
- Épinglez par hash : les tags sont mutables, les SHA ne le sont pas
- Runners éphémères : détruire le runner après chaque job empêche la persistance
- Signez vos artefacts : prouvez leur origine et leur intégrité
- Privilégiez les contrôles structurels (impossibles à contourner) aux contrôles ponctuels
Liens utiles
- Sécurité de la supply chain — Vue d’ensemble
- SLSA — niveaux de confiance — Modèle de garanties
- SBOM — Software Bill of Materials — Inventaire des composants
- VEX — Exploitabilité des vulnérabilités — Prioriser les risques
- Cosign — Signature des artefacts — Vérifier l’origine
- Syft — Générer des SBOM — Inventaire automatisé
- OpenSSF Scorecard — Évaluer la santé des projets
- Épingler par SHA (GitHub Actions) — Sécuriser les actions
- Confiance implicite dans les pipelines — Pourquoi c’est dangereux
- Pourquoi bloquer la pipeline ne suffit pas — Limites de l’approche punitive