Sécuriser une pipeline GitLab CI/CD sans ralentir vos livraisons
SAST, scan de dépendances et d'images, secrets, SBOM, signature cosign : comment intégrer la sécurité dans GitLab CI/CD sans freiner vos mises en production.
Beaucoup d'équipes voient la sécurité comme un frein : un scan de vingt minutes, des centaines d'alertes que personne ne lit, des déploiements bloqués pour une vulnérabilité sans impact réel. Résultat, les contrôles sont contournés ou désactivés. Chez Cloud Corner, nous partons du principe inverse : une pipeline bien conçue rend la sécurité invisible tant que tout va bien, et bruyante uniquement quand un risque réel apparaît. Voici notre approche pour GitLab CI/CD.
Le principe : décaler à gauche, mais intelligemment
Le « shift left » ne consiste pas à tout exécuter à chaque commit. Il s'agit de placer chaque contrôle au moment où il coûte le moins cher et apporte le plus d'information :
- Au commit : détection de secrets et SAST, rapides et incrémentaux.
- À la merge request : scan des dépendances, analyse des fichiers Dockerfile et d'infrastructure.
- Au build : scan de l'image, génération du SBOM, signature.
- Au déploiement : vérification de la signature et des politiques d'admission.
Les jobs de sécurité tournent en parallèle des tests, jamais en série derrière eux. C'est le premier levier pour ne pas allonger le temps de pipeline.
Les briques à intégrer
SAST avec Semgrep
Semgrep analyse le code source avec des règles lisibles et facilement extensibles. Nous le lançons uniquement sur les fichiers modifiés en merge request, et sur l'ensemble du dépôt lors d'un passage planifié nocturne.
Scan des dépendances et des images
Les dépendances applicatives (lockfiles npm, pip, Maven) et les images de conteneurs sont la source la plus fréquente de vulnérabilités connues. Trivy couvre les deux avec un seul outil, en mode « filesystem » pour le code et en mode « image » pour le résultat du build.
Détection de secrets
Gitleaks ou la détection native de GitLab repèrent les clés d'API et mots de passe committés. Activez-la aussi en pré-commit côté développeur : un secret qui n'entre jamais dans l'historique Git n'a pas besoin d'être révoqué.
SBOM et signature
Un SBOM (au format CycloneDX ou SPDX) liste précisément ce que contient votre artefact. Associé à une signature cosign, il permet de prouver l'origine d'une image et de réagir en quelques minutes lorsqu'une nouvelle faille est publiée.
Un exemple de pipeline avec to-be-continuous
Le framework to-be-continuous fournit des composants GitLab prêts à l'emploi qui évitent de maintenir des dizaines de lignes de YAML. Voici un extrait réaliste :
include:
- component: $CI_SERVER_FQDN/to-be-continuous/docker/gitlab-ci-docker@6
inputs:
trivy-enabled: true
sbom-disabled: false
- component: $CI_SERVER_FQDN/to-be-continuous/semgrep/gitlab-ci-semgrep@3
- component: $CI_SERVER_FQDN/to-be-continuous/gitleaks/gitlab-ci-gitleaks@3
stages:
- build
- test
- package-build
- package-test
- publish
- deploy
sign-image:
stage: publish
image:
name: gcr.io/projectsigstore/cosign:v2.4.1
entrypoint: [""]
id_tokens:
SIGSTORE_ID_TOKEN:
aud: sigstore
script:
- cosign sign --yes "$CI_REGISTRY_IMAGE@$(cat digest.txt)"
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
Le job de signature utilise un jeton OIDC émis par GitLab (id_tokens) : aucune clé privée n'est stockée dans le projet. C'est la signature « keyless » de Sigstore, vérifiable ensuite par l'identité de la pipeline.
Pensez à épingler les versions des composants et des images d'outils, idéalement par digest. Une pipeline de sécurité qui tire un latest est elle-même un risque de chaîne d'approvisionnement.
Une politique qui ne bloque que l'exploitable
Bloquer sur chaque CVE est le meilleur moyen de se faire contourner. Notre règle de base :
- Bloquer les vulnérabilités de sévérité haute ou critique, avec un correctif disponible, dans un composant réellement présent à l'exécution.
- Alerter sans bloquer pour le reste, avec un ticket créé automatiquement et une échéance.
- Ignorer explicitement les faux positifs et les risques acceptés, dans un fichier versionné, avec un motif et une date d'expiration.
Pour Trivy, cela donne par exemple :
trivy-image:
stage: package-test
image:
name: aquasec/trivy:0.58.0
entrypoint: [""]
script:
- trivy image
--severity HIGH,CRITICAL
--ignore-unfixed
--ignorefile .trivyignore.yaml
--exit-code 1
"$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA"
L'option --ignore-unfixed écarte les failles sans correctif disponible : bloquer sur ce qu'on ne peut pas corriger n'aide personne. Le fichier d'exceptions peut ressembler à ceci :
vulnerabilities:
- id: CVE-2025-00000
statement: "Fonction vulnérable non appelée par notre code"
expired_at: 2026-12-31
L'expiration est essentielle : une exception sans date devient vite une dette oubliée. Pour affiner la priorisation, croisez la sévérité avec la présence de la faille dans le catalogue KEV de la CISA ou son score EPSS, qui estiment l'exploitation réelle.
Gérer les secrets proprement
Le meilleur secret est celui qui n'existe pas. Par ordre de préférence :
- OIDC fédéré : la pipeline s'authentifie auprès du cloud (AWS, GCP, Azure) ou de Vault avec un jeton court, lié au projet et à la branche. Aucun identifiant statique.
- HashiCorp Vault : les secrets sont lus à la volée via
secrets:dans le job, avec des politiques en moindre privilège. - Variables CI/CD : en dernier recours, toujours masquées (absentes des logs), protégées (disponibles uniquement sur les branches et tags protégés) et limitées à l'environnement concerné.
Exemple de lecture depuis Vault avec un jeton OIDC :
deploy:
stage: deploy
id_tokens:
VAULT_ID_TOKEN:
aud: https://vault.example.org
secrets:
DB_PASSWORD:
vault: production/db/password@secret
file: false
script:
- ./deploy.sh
environment: production
Mesurer pour ne pas ralentir
Une pipeline sécurisée reste une pipeline rapide si l'on garde quelques réflexes :
- exécuter les scans en parallèle des tests avec
needs, pas après ; - mettre en cache les bases de vulnérabilités de Trivy entre les jobs ;
- limiter les scans complets aux branches principales et aux exécutions planifiées ;
- suivre le temps moyen de pipeline et le délai de correction des vulnérabilités, deux indicateurs qui disent si la sécurité aide ou gêne vos équipes.
Déployer progressivement
Inutile de tout activer le même jour. Nous recommandons de commencer en mode « observation » : les jobs tournent, remontent leurs résultats dans la merge request, mais ne bloquent rien (allow_failure: true). Après deux ou trois semaines, vous connaissez le bruit de fond, vous avez traité les faux positifs évidents et vous pouvez passer les contrôles les plus fiables en mode bloquant. Cette montée en charge évite le rejet par les équipes, qui voient la sécurité comme une aide plutôt que comme une sanction.
Désignez aussi un responsable par projet pour le traitement des alertes. Une alerte sans propriétaire finit toujours par être ignorée, quel que soit l'outil.
Besoin d'un coup de main ?
Intégrer ces contrôles dans vos pipelines existantes, définir une politique réaliste ou migrer vos secrets vers OIDC et Vault demande un peu de méthode. Si vous souhaitez un regard extérieur ou un accompagnement, n'hésitez pas à nous contacter.
Un projet similaire ?
Parlons-en : un expert vous répond sous 24 heures ouvrées.
À lire aussi
Application mobile : native, Flutter, PWA ou Tauri 2, comment choisir ?
Native, cross-platform, PWA ou Tauri 2 : comparatif concret selon l'accès matériel, le hors-ligne, la maintenance et la publication sur les stores.
SEO technique avec Nuxt : le guide pour un site rapide et bien référencé
Rendu SSR ou pré-rendu, useSeoMeta, canoniques, sitemap, JSON-LD, Core Web Vitals : les réglages SEO techniques à maîtriser sur un site Nuxt 4.
GitOps avec Flux CD : piloter Kubernetes depuis Git, sans kubectl en production
GitOps avec Flux CD sur Kubernetes : structure de dépôt, Kustomization, HelmRelease, secrets SOPS, promotion entre environnements et validation en CI.