Sécurité CI/CD : trois erreurs qui coûtent cher
240 %. C'est la hausse documentée des incidents de supply chain logicielle sur trois ans, publiée par le rapport SLSA 2025.

Sécurité CI/CD: trois erreurs qui coûtent cher
Derrière ce chiffre, une réalité opérationnelle souvent sous-estimée: un pipeline d'intégration continue mal configuré reste l'un des vecteurs d'attaque les plus rentables pour un acteur malveillant. Trois erreurs récurrentes — gestion déficiente des secrets, permissions excessives, dépendances non verrouillées — expliquent l'essentiel des compromissions observées depuis SolarWinds (2020) jusqu'à Codecov (2021). Les aborder comme un problème de configuration isolé revient à manquer la nature systémique du risque.
On ne sécurise pas un pipeline en ajoutant un outil. On le sécurise en réduisant sa surface d'attaque, en raccourcissant la durée de vie des credentials et en traçant chaque dépendance jusqu'à sa source vérifiable. Ce guide-cartographie décompose les trois failles les plus coûteuses, expose les mécanismes techniques qui les rendent exploitables et propose les contre-mesures minimales exigibles pour toute infrastructure de production.
Le piège des secrets statiques: pourquoi vos clés API sont en danger
Le premier point de défaillance reste la gestion des identifiants. Clés d'API, jetons AWS, certificats TLS, tokens de registries: dès lors qu'un secret statique longue durée est inscrit dans un fichier de configuration, versionné dans un dépôt ou copié dans un log de build, l'environnement devient exposé tant que la révocation manuelle n'a pas eu lieu. Le problème n'est pas la fuite en elle-même — elle survient toujours — c'est la fenêtre d'exposition.
Un secret statique confère à son détenteur un accès permanent, réutilisable hors du contexte d'émission, et indétectable tant qu'aucune rotation n'est déclenchée. Les journaux d'audit cloud voient une authentification légitime. La compromission devient silencieuse.
Les vecteurs d'exposition les plus fréquents:
- Fichiers
.envouconfig.ymlversionnés par inadvertance dans le dépôt source. - Jetons copiés dans la sortie standard d'un job pour des raisons de débogage.
- Secrets partagés entre plusieurs pipelines via des variables d'organisation trop permissives.
- Clés d'API utilisées simultanément en développement local et en production, sans cloisonnement.
Un secret statique n'est pas une clé d'accès. C'est une bombe à retardement dont la mèche est la prochaine fuite de log.
La remédiation passe par un changement de paradigme: remplacer les secrets persistants par des jetons éphémères, limités à la durée du job, émis à la demande et révocables instantanément. C'est précisément le rôle du protocole OIDC, détaillé plus loin. En attendant, trois mesures immédiates s'imposent: ne jamais versionner un secret, auditer l'historique git pour identifier les fuites passées, et centraliser la distribution via un vault dédié plutôt qu'un copier-coller dans l'interface CI.
Permissions excessives: le risque du privilège « write-all » dans vos workflows
Le deuxième défaut structurel concerne l'octroi de permissions. Par défaut, de nombreux orchestrateurs proposent des scopes généreux — écriture sur l'ensemble du dépôt, push sur le registre d'images, déploiement sur l'environnement cloud. Cette commodité a un prix: un seul job compromis suffit alors pour pivoter vers l'ensemble du système.
Le mécanisme d'exploitation est direct. Un attaquant injecte une commande malveillante dans une étape de build (via une dépendance piégée, un script tiers ou une injection dans une variable d'environnement). Le job s'exécute avec les droits accordés au pipeline. Si ces droits sont larges, l'attaquant pousse une image corrompue vers le registre, modifie des fichiers d'infrastructure as code ou exfiltre des données de production.
Le tableau ci-dessous résume les écarts de risque les plus courants entre une configuration par défaut et une configuration alignée sur le principe du moindre privilège.
| Paramètre | Configuration par défaut | Configuration renforcée |
|---|---|---|
| Scope du token GitHub/GitLab | write-all (repo + packages + deployments) | contents: read + scopes ciblés par job |
| Durée du jeton cloud | Statique, persistant après le job | Éphémère via OIDC, expiration en quelques minutes |
| Accès au registre d'images | Push autorisé depuis tous les jobs | Push limité aux jobs de release taggués |
| Permissions filesystem | Root ou utilisateur à larges droits | Utilisateur non-root, système de fichiers monté en lecture seule hors cache |
| Variables d'environnement | Toutes accessibles, y compris secrètes | Segmentation explicite par étape, masquage des logs |
Le moindre privilège n'est pas une option. C'est la condition sine qua non pour qu'un job compromis reste un incident contenu, et non une brèche systémique.
La bascule opérationnelle consiste à cartographier les droits effectivement nécessaires par étape, puis à n'accorder que ces droits. Sur GitHub Actions, cela se traduit par l'utilisation des permissions: au niveau du workflow et des scopes minimaux (contents: read pour un job de test, packages: write uniquement pour un job de publication). Sur GitLab CI, le mécanisme équivalent passe par les rules: conditionnels et l'usage de id_tokens liés à OIDC. Le coût de mise en œuvre est marginal; le bénéfice en résilience est asymétrique.
Supply chain logicielle: sécuriser les dépendances et actions tierces
Le troisième angle mort est la chaîne d'approvisionnement logicielle. Un pipeline CI/CD moderne ne se construit pas seul: il agrège des dizaines d'actions tierces, de bibliothèques et d'images de base. Chacune de ces dépendances est un vecteur d'attaque potentiel. Le rapport SLSA 2025 chiffre à +240 % la progression des incidents ciblant précisément cette chaîne sur les trois dernières années.
Deux vecteurs dominent:
1. Poisoned Pipeline Execution (PPE): compromission d'une action tierce utilisée par le workflow. L'action, apparemment légitime, exécute du code arbitraire dans le contexte du job.
2. Typosquatting: une dépendance malveillante exploite une faute de frappe ou une ressemblance nominale pour s'introduire dans la résolution de paquets.
La défense repose sur le pinning par hash. Au lieu de référencer une action par son tag mutable (par exemple @v3), on la verrouille à un commit précis identifié par son empreinte SHA-256. Le tag peut être déplacé; le hash, non. Cette pratique, recommandée par OWASP et par la documentation officielle de GitHub, transforme une dépendance dynamique en un composant vérifiable et reproductible.
Le coût de mise en œuvre: quelques minutes par action référencée. Le bénéfice: suppression de la classe d'attaque par injection de tag malveillant. Le compromis est favorable, à condition de maintenir une procédure de mise à jour régulière des hashes — un hash figé trop longtemps finit par devenir une dette de maintenance.
Mesures complémentaires à appliquer sans délai:
- Verrouiller les images de base par digest, pas par tag.
- Activer la vérification de signature des artefacts (cosign, SLSA provenance).
- Segmenter les sources de paquets: un miroir interne validé plutôt qu'un registre public ouvert.
- Auditer trimestriellement la liste des actions tierces effectivement appelées.
Vers une architecture Zero Trust: l'adoption du protocole OIDC
Les trois erreurs précédentes partagent une racine commune: la persistance de la confiance. Un secret statique est une confiance indéfiniment reconduite. Un scope large est une confiance étendue sans vérification continue. Une dépendance non verrouillée est une confiance aveugle envers l'éditeur tiers.
Le protocole OIDC (OpenID Connect) casse cette logique en remplaçant les identifiants statiques par des jetons éphémères émis à la demande par un fournisseur d'identité. Concrètement: un job GitHub Actions demande un jeton d'accès au cloud provider; le fournisseur vérifie l'identité du job via OIDC et émet un token valable quelques minutes, automatiquement révoqué à la fin de l'exécution.
Les avantages opérationnels sont immédiats:
- Aucun secret à stocker, à rotater ou à protéger dans le vault.
- Fenêtre d'exploitation réduite à la durée du job.
- Révocation automatique, sans intervention manuelle.
- Traçabilité fine: chaque jeton est rattaché à un workflow, un commit, un runner.
La mise en œuvre technique varie selon l'orchestrateur. Sur GitHub Actions, elle passe par la configuration d'une trust relationship entre le dépôt (ou l'organisation) et le compte cloud, puis par l'usage du bloc permissions: id-token: write au niveau du job. Sur GitLab CI, le mécanisme équivalent est id_tokens avec un claim personnalisé. Le temps de configuration initial se compte en heures, pas en jours. Le retour sur investissement se mesure en réduction drastique de la surface d'attaque.
Le référentiel OWASP Top 10 CI/CD comme boussole de gouvernance
Face à la multiplication des vecteurs, un référentiel dédié est apparu: l'OWASP Top 10 CI/CD Security Risks. Distinct du OWASP Top 10 Web (qui traite des vulnérabilités applicatives comme XSS ou injection SQL), ce classement cible spécifiquement les risques propres aux chaînes d'intégration et de déploiement continus.
Parmi les catégories documentées, trois recoupent directement les erreurs analysées dans ce guide:
- CICD-SEC-1: Contrôles d'accès insuffisants — correspond aux permissions excessives.
- CICD-SEC-4: Mauvaise hygiène des secrets — correspond aux secrets statiques.
- CICD-SEC-6: Abus de dépendances tierces — correspond à la supply chain non verrouillée.
Utiliser ce référentiel comme grille d'audit permet de sortir d'une approche au cas par cas pour adopter une couverture systématique. On ne sécurise plus un pipeline; on vérifie qu'il respecte un standard reconnu, documenté et opposable.
Conclusion: la checklist opérationnelle
La sécurisation d'un pipeline CI/CD ne se résume pas à empiler des outils. Elle procède d'une réduction disciplinée de la surface d'attaque, durée par durée, droit par droit, dépendance par dépendance. Les trois erreurs documentées ci-dessus partagent une même racine — la persistance d'éléments de confiance non renouvelables — et une même réponse: éphémère, segmenté, vérifié.
Un pipeline sécurisé n'est pas un pipeline sans incident. C'est un pipeline où chaque incident reste contenu, tracé et réversible.
Checklist d'audit immédiat:
- Aucun secret statique dans le dépôt, les fichiers
.envou les logs de job. - Tokens cloud migrés vers OIDC, avec expiration automatique en minutes.
- Permissions par job réduites au strict nécessaire (
contents: readpar défaut). - Toutes les actions tierces verrouillées par hash SHA-256, pas par tag.
- Images de base référencées par digest, avec vérification de signature activée.
- Audit trimestriel de la liste des dépendances et actions effectivement utilisées.
- Référentiel OWASP Top 10 CI/CD appliqué comme grille de revue avant chaque release majeure.
- Procédure documentée de révocation d'urgence en cas de compromission avérée d'une dépendance.
Les chiffres sont têtus: +240 % d'incidents en trois ans, deux compromissions majeures documentées en 18 mois (SolarWinds, Codecov), un référentiel OWASP désormais stabilisé. Les organisations qui continuent de traiter la sécurité du pipeline comme un sujet de tooling accumulent une dette technique qui se rappelle à elles le jour de l'incident. Les autres traitent le pipeline comme ce qu'il est devenu: un composant critique de l'infrastructure, au même titre qu'un pare-feu ou qu'un système d'authentification.