
Une pull request qui modifie le Dockerfile peut exécuter du code pendant la construction. Si le runner détient aussi les accès de production, le pipeline devient un chemin d'administration : construisez une séparation vérifiable entre contribution, artefact et déploiement.
1. Diagnostiquer les frontières de confiance
Prévoyez un dépôt de test, un registre privé avec espace de quarantaine, Docker Buildx, jq, Trivy et Cosign installés depuis des distributions vérifiées et épinglés à des versions testées. Le service de signature doit déjà posséder sa clé protégée ; les déployeurs disposent seulement de la clé publique approuvée release.pub.
Inventoriez runners GitHub/GitLab, workflows, fichiers inclus, variables, tokens, caches et droits de registre. Depuis le dépôt de laboratoire :
git ls-files '.github/workflows/*' '.gitlab-ci.yml'git ls-files '*Dockerfile*' '*lock*' '*.env*'docker buildx versiontrivy --versioncosign versiontrivy fs --scanners vuln,secret --exit-code 1 .Ce scan du répertoire courant ne couvre pas tout l'historique Git. Activez aussi un contrôle de secrets sur l'historique et la protection des pushes disponibles dans votre forge. Traitez chaque détection avant de relancer.
Architecture cible : PR sans secrets → runner éphémère → tests ; commit approuvé → runner de construction → registre de quarantaine → scans et signature → approbation de production → déploiement par digest. Aucun code non approuvé ne doit obtenir le réseau ou les credentials du runner de publication.
Sur GitHub, commencez avec permissions: contents: read, puis accordez les permissions supplémentaires au seul job qui en a besoin. Sur GitLab, séparez les runners de branches protégées et les variables de production. Dans les deux cas, le masquage d'une variable n'empêche pas un script malveillant de la voler.
2. Construire un artefact contrôlable
Faites approuver toute modification des workflows, Dockerfiles et fichiers de dépendances. Épinglez les actions à un SHA complet vérifié, les images de base par digest et les dépendances via un lockfile maintenu. Ne montez pas le socket Docker d'un hôte partagé dans un job non fiable. Utilisez des runners jetables avec caches séparés par niveau de confiance.
Avant construction, ajoutez au .dockerignore :
.git.env.env.**.pem*.keyCela exclut ces fichiers du contexte ; cela ne nettoie ni Git ni les anciennes couches. Pour une dépendance privée, utilisez un secret BuildKit au lieu de ARG ou ENV. Exemple de fragment Dockerfile pour un projet Node dont les manifests sont déjà copiés :
RUN --mount=type=secret,id=npmrc NPM_CONFIG_USERCONFIG=/run/secrets/npmrc npm ci --ignore-scriptsLa construction correspondante ajoute --secret id=npmrc,src=/run/ci/npmrc. Le fichier provient d'un gestionnaire de secrets, hors dépôt. N'autorisez jamais un Dockerfile non approuvé à recevoir ce secret ; le code du build peut le lire. Réactivez les scripts d'installation uniquement après analyse des besoins.
Dans le job de confiance, déjà authentifié au registre avec un token limité, adaptez IMAGE et TAG :
set -euIMAGE=registry.example.com/quarantine/shopTAG=reviewed-commitdocker buildx build --sbom=true --provenance=mode=max --metadata-file build.json --push -t "$IMAGE:$TAG" .DIGEST=$(jq -r '."containerimage.digest"' build.json)test "$DIGEST" != nullREF="$IMAGE@$DIGEST"trivy image --scanners vuln,secret --severity HIGH,CRITICAL --exit-code 1 "$REF"docker buildx imagetools inspect "$REF"Les findings sont une barrière proposée, à ajuster avec exceptions datées. Une erreur réseau du scanner doit aussi bloquer la promotion. Les attestations accompagnent ici l'image poussée ; le SBOM ne constitue pas un scan, et une provenance n'est pas à elle seule une preuve de confiance. Ne passez aucun secret comme build argument : il peut apparaître dans la provenance.
Le service de signature autorisé signe uniquement le digest approuvé après les contrôles. Le job de déploiement vérifie ensuite :
cosign verify --key release.pub "$REF" > verified-signature.jsondocker pull "$REF"Distribuez release.pub par un canal protégé, jamais depuis la même PR. Exigez également que le digest corresponde au commit attendu et à sa provenance validée. La signature d'un artefact différent ne vaut pas autorisation de déployer.
3. Tester le refus et organiser le retour arrière
En laboratoire, un digest non signé, une dépendance de test vulnérable et un faux secret de test doivent empêcher la promotion. Vérifiez que le registre public ou de production n'est pas accessible au job de PR et que les tags de release ne sont pas réécrits. OIDC peut remplacer des tokens durables lorsque le fournisseur le permet ; restreignez identité, dépôt, branche, environnement et audience.
Surveillez modifications des workflows, inscriptions de runners, usages de tokens, pushes de registre, échecs de signature, âge des bases de vulnérabilités et durée des scans. Le SBOM et les scans augmentent temps de build, stockage et trafic ; mesurez-les et mettez en cache les bases, sans réutiliser un espace de travail non fiable.
Conservez le digest signé de la dernière version saine et son schéma de base compatible. Un rollback redéploie ce digest, pas un tag mutable ; répétez-le en préproduction. Si le runner est compromis, stoppez les publications, révoquez ses accès, conservez ses journaux et reconstruisez-le depuis une image saine. Ne revenez pas à un runner suspect pour gagner du temps.
Sources : GitHub, sécurisation des workflows, Docker, SBOM et provenance.
Retrouvez-le dans nos publications
Les étapes clés de cet article, en carrousel. Suivez-nous pour découvrir les prochaines. Nos publications sont rédigées en anglais.




