Sécurité CI/CD : rendre votre pipeline un atout DevSecOps, pas une porte d’entrée
CI/CD (Continuous Integration / Continuous Delivery) désigne l’automatisation qui construit, teste et déploie votre logiciel à chaque changement de code. GitHub Actions, GitLab CI/CD et Jenkins en sont des implémentations courantes. Quand tout va bien, vous gagnez en vélocité et en qualité. Quand la sécurité du pipeline est négligée, ce même automate peut exécuter du code malveillant, exfiltrer des secrets ou pousser une image Docker compromise vers la production — au cœur même de votre DevSecOps.
Ce guide explique comment concevoir un pipeline sécurisé : menaces réelles, erreurs fréquentes, scans SAST, SCA, DAST, gestion des secrets et principe du moindre privilège, avec des exemples concrets autour de GitHub Actions et des images conteneurisées.
CI/CD en deux minutes : pourquoi c’est le nerf de la livraison
- Intégration continue (CI) : à chaque commit ou merge, le pipeline compile, exécute les tests, lance des analyses — vous savez rapidement si le code « casse » quelque chose.
- Livraison / déploiement continu (CD) : une fois les critères validés, l’artefact (binaire, image Docker, chart Helm…) est publié ou déployé selon des règles que vous définissez.
Le pipeline a souvent accès à des secrets (registres, cloud, bases de données) et exécute des scripts et des dépendances téléchargées depuis Internet. C’est exactement ce qui en fait une cible : compromettre le CI/CD, c’est potentiellement agir avec les mêmes droits que votre équipe de release.
Pourquoi sécuriser son pipeline est critique
Un pipeline mal verrouillé ne se limite pas à une « mauvaise config » : il peut devenir le maillon faible de toute l’organisation.
- Surface d’attaque concentrée : un seul fichier
.github/workflows/*.ymlou.gitlab-ci.ymlpeut déclencher des jobs sur des runners avec accès réseau et secrets. - Effet domino : une image Docker construite dans un pipeline non fiable peut être déployée partout (Kubernetes, VM, edge). La sécurité des conteneurs commence souvent dans le CI.
- Alignement DevSecOps : intégrer la sécurité dans le cycle de vie logiciel sans sécuriser le pipeline revient à poser une alarme sur une porte laissée ouverte.
Les moteurs de recherche et les équipes recherchent aujourd’hui des réponses précises sur la sécurité CI/CD, le pipeline sécurisé et le DevSecOps CI/CD — parce que les incidents réels (fuites de secrets, supply chain) sont devenus visibles dans la presse technique.
Scénarios d’attaque : ce qui arrive vraiment
Vol et fuite de secrets
Les tokens (PAT, CI_JOB_TOKEN, clés cloud) finissent dans les logs de job, dans une issue, ou dans un fork public après un PR. Un attaquant récupère un secret avec accès au registry ou au cluster : il ne « casse » pas l’application, il devient le pipeline.
Exemple réaliste : un script affiche par erreur echo $MY_SECRET ou la variable est interpolée dans une commande loguée en clair. Les scanners de secrets (gitleaks, GitHub secret scanning) existent précisément pour réduire ce risque.
Injection dans le pipeline
Si n’importe qui peut modifier un workflow ou si une PR exécute du code non revu sur un runner avec secrets, un contributeur malveillant peut ajouter une étape qui envoie des variables d’environnement vers un serveur externe. Les plateformes durcissent ce point (pull_request vs pull_request_target, approbations, environnements protégés) — ignorer ces modèles expose à l’injection de commandes ou de YAML.
Dépendances malveillantes (supply chain)
Un package npm ou PyPI peut être compromis, ou un typosquatting peut tromper un développeur. Le pipeline installe ces dépendances à chaque build : SCA (Software Composition Analysis) et verrouillage de versions (lockfile, SBOM) sont des réponses structurées, complétées par la veille sur la boîte à outils.
Erreurs fréquentes (et comment les éviter)
- Secrets en dur dans le dépôt — jamais ; utiliser les secrets natifs (
secrets.*sur GitHub, variables masquées sur GitLab, credentials Jenkins chiffrés ou via un vault). - Permissions
contents: writeouid-tokentrop larges pour un job qui ne fait qu’une analyse statique : réduire au strict nécessaire (moindre privilège). - Pas de scan d’image Docker avant push : l’image « passe » en production avec des CVE connues sur le socle
FROM. - Ignorer les forks et les workflows déclenchés par PR : une politique de branch protection et de review obligatoire limite les workflows dangereux.
- Déployer sans gate : un build vert avec des vulnérabilités critiques non traitées — définir des seuils (bloquer si CVE critique sans exception documentée).
Bonnes pratiques avancées : secrets, SAST, SCA, DAST et Docker
Gestion des secrets dans le pipeline
Référencez toujours les secrets via le mécanisme de la plateforme — exemple GitHub Actions :
- name: Déploiement
env:
API_KEY: ${{ secrets.PRODUCTION_API_KEY }}
run: ./deploy.sh
Ne jamais commiter :
# ❌ À proscrire
# run: ./deploy.sh --key "abc123"
Rotation des secrets, séparation prod / non-prod, et environnements avec approbation manuelle pour la production lorsque c’est pertinent.
SAST, SCA et DAST dans un pipeline sécurisé
- SAST (Static Application Security Testing) : analyse du code source pour des motifs vulnérables (injections, mauvaises API crypto).
- SCA : inventaire et vulnérabilités des dépendances tierces — indispensable face aux attaques supply chain.
- DAST (Dynamic Application Security Testing) : tests contre une instance déployée (souvent hors du build initial, ou sur un environnement de staging).
Intégration type GitHub Actions avec un outil SCA (illustratif) :
- name: Analyse des dépendances (SCA)
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
args: --severity-threshold=high
Combinez cela avec des politiques de branche : le merge n’est possible que si le job de sécurité est vert ou qu’une exception est tracée.
Sécurité Docker dans le pipeline : build + scan
Construire une image puis la scanner avant publication limite les risques côté orchestration et runtime :
- name: Build image
run: docker build -t myapp:${{ github.sha }} .
- name: Scan Trivy
uses: aquasecurity/trivy-action@master
with:
image-ref: myapp:${{ github.sha }}
format: sarif
output: trivy-results.sarif
Bonnes habitudes : utilisateur non-root dans le Dockerfile, tags immuables (sha du commit plutôt que latest seul pour la traçabilité), et registry privé avec contrôle d’accès.
Principe du moindre privilège
Pour chaque job, demandez : de quel accès a-t-il réellement besoin ? — lecture seule sur le dépôt pour un lint, pas d’accès aux secrets de production pour un job de documentation. Sur GitHub, utilisez permissions: au niveau du workflow ; sur GitLab, rôles et environnements ; sur Jenkins, credentials par dossier ou par pipeline. Moins de droits = moins de dégâts en cas de compromission.
Côté applicatif, ce que vous déployez via ce pipeline doit aussi rester sain : revoir la sécurité API (auth, validation) pour éviter que l’automatisation ne livre vite une surface vulnérable.
Conclusion
La sécurité CI/CD n’est pas une option réservée aux grandes entreprises : c’est la condition pour que l’automatisation reste un multiplicateur de confiance plutôt qu’un amplificateur d’incidents. En traitant secrets, analyse statique et composition, images conteneurisées et permissions avec rigueur, vous ancrez le DevSecOps dans la chaîne réelle de livraison — là où le code devient artefact puis service.
Poursuivez avec les ressources OmbreLoup Sec : DevSecOps Basics, Sécurité API, Docker & Kubernetes et Outils & Ressources pour outiller et approfondir votre pipeline sécurisé sans sacrifier la vélocité.