Épingler chaque action sur le SHA de son commit ferme la porte aux tags déplacés. Mais un SHA fige aussi les correctifs : sans mécanisme de mise à jour, la bonne pratique devient une dette. Cette page montre comment tenir un parc épinglé dans la durée, avec Dependabot ou Renovate, et pourquoi le point critique n'est pas l'outil mais le tri de la file.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Mesurer la dette que crée un épinglage non maintenu
- Configurer Dependabot pour les actions, les images et les dépendances
- Réduire le bruit par le groupement et la fenêtre de quarantaine
- Trier la file sans l'accumuler, et décider quoi fusionner automatiquement
- Rejouer les digests d'images de base, que Dependabot ne couvre pas toujours
La dette d'épinglage, mesurée
Section intitulée « La dette d'épinglage, mesurée »Le raisonnement abstrait convainc mal. Voici l'état d'un dépôt de référence exemplaire par ailleurs (permissions minimales, scanners en CI, provenance SLSA, signature Cosign, note OpenSSF Scorecard soignée), audité en septembre 2026, dont la file Dependabot n'avait pas été traitée depuis le 16 juillet, soit sept semaines.
| Élément épinglé | Version en place | Version courante | Écart |
|---|---|---|---|
actions/checkout | v7.0.0 | v7.0.1 | 1 correctif |
docker/login-action | v4.4.0 | v4.5.0 | 1 version mineure |
getplumber/plumber | v0.4.6 | v0.4.60 | 54 versions |
python:3.11-slim | digest de juillet | digest du 2 septembre | image non corrigée |
Trois conséquences, toutes constatées :
- La CI est tombée d'elle-même. Le job de scan d'image échouait sur chaque
pull request, y compris celles qui ne touchaient ni le
Dockerfileni les dépendances. Le digest épinglé ne recevant aucun correctif, il a suffi qu'une CVE corrigée en amont soit publiée pour que le seuilHIGH,CRITICALsoit franchi. - La documentation a divergé du code. Les guides citaient des épinglages que le dépôt ne portait plus, alors qu'ils annonçaient commenter ses fichiers réels.
- Dix pull requests s'étaient empilées, au point de rendre la file elle-même décourageante à traiter.
Configurer Dependabot
Section intitulée « Configurer Dependabot »Dependabot lit le commentaire de version placé après le SHA pour savoir où vous en êtes. C'est la raison pour laquelle ce commentaire n'est pas décoratif : sans lui, l'outil ne sait pas comparer.
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1La configuration minimale couvre les trois écosystèmes d'un dépôt conteneurisé :
version: 2updates: - package-ecosystem: "github-actions" directory: "/" schedule: interval: "weekly"
- package-ecosystem: "docker" directory: "/" schedule: interval: "weekly"
- package-ecosystem: "pip" directory: "/" schedule: interval: "weekly"Notez la déclaration docker : sans elle, l'image de base reste sur son
digest indéfiniment, et c'est exactement le scénario qui a fait tomber la CI
mesurée plus haut.
Réduire le bruit avant qu'il ne décourage
Section intitulée « Réduire le bruit avant qu'il ne décourage »Une file de dix pull requests ne se traite pas, elle s'ignore. Deux réglages divisent le volume sans rien perdre.
Le groupement rassemble plusieurs mises à jour dans une seule pull request :
- package-ecosystem: "github-actions" directory: "/" schedule: interval: "weekly" groups: actions-patch: update-types: ["patch"] actions-minor: update-types: ["minor"]La fenêtre de quarantaine (cooldown) retarde la proposition d'une version
fraîchement publiée. L'intérêt est de sécurité, pas de confort : une version
compromise est généralement retirée en quelques heures ou quelques jours, et
attendre suffit à ne jamais la voir passer.
cooldown: default-days: 7L'alternative Renovate
Section intitulée « L'alternative Renovate »Renovate offre un réglage que Dependabot n'a pas, et qui compte pour un parc
épinglé : pinDigests, qui convertit et maintient les références par
digest, y compris pour les images.
{ "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": ["config:recommended"], "github-actions": { "enabled": true, "pinDigests": true }, "docker": { "pinDigests": true }, "minimumReleaseAge": "7 days"}Le choix entre les deux se résume ainsi : Dependabot est intégré, sans service tiers à autoriser, et suffit si vos actions portent déjà leurs commentaires de version. Renovate se configure plus finement, sait épingler lui-même ce qui ne l'est pas encore, et regroupe mieux. Sur un dépôt unique, Dependabot suffit ; sur un parc de dizaines de dépôts, Renovate devient rentable.
Trier la file : la partie qui échoue vraiment
Section intitulée « Trier la file : la partie qui échoue vraiment »L'outillage n'est jamais le problème. Dans le cas mesuré plus haut, Dependabot fonctionnait parfaitement : il avait proposé toutes les mises à jour manquantes, en temps voulu. Personne ne les avait regardées.
Une règle de tri tient en trois lignes, et la difficulté est de s'y tenir.
| Type de mise à jour | Décision | Condition |
|---|---|---|
| Patch sur une action ou une image | Fusion, éventuellement automatique | CI verte, y compris le scan de workflows |
| Mineure | Fusion après lecture du changelog | CI verte |
| Majeure | Revue explicite, jamais en lot | CI verte et changelog lu |
Automatiser les patchs, sous condition
Section intitulée « Automatiser les patchs, sous condition »L'auto-fusion des patchs n'est défendable que si votre CI est réellement bloquante. Un dépôt qui fait passer actionlint, zizmor, poutine et un gate de posture à seuil strict peut se le permettre : la porte est gardée par les scanners, pas par l'attention humaine.
name: Dependabot auto-merge
on: pull_request_target
permissions: {}
jobs: automerge: if: github.actor == 'dependabot[bot]' runs-on: ubuntu-24.04 permissions: contents: write pull-requests: write steps: - name: Récupérer les métadonnées de la mise à jour id: meta uses: dependabot/fetch-metadata@25dd0e34f4fe68f24cc83900b1fe3fe149efef98 # v3.1.0 - name: Activer l'auto-fusion pour les patchs if: steps.meta.outputs.update-type == 'version-update:semver-patch' env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} PR_URL: ${{ github.event.pull_request.html_url }} run: gh pr merge --auto --squash "$PR_URL"Deux points de vigilance sur cet exemple. Le déclencheur est
pull_request_target, nécessaire pour que le jeton dispose des droits
d'écriture sur une pull request de Dependabot ; le workflow ne checkoute
jamais le code de la branche, ce qui le maintient dans le cas d'usage sûr
décrit dans Sécuriser pull_request_target.
Et gh pr merge --auto n'outrepasse rien : la fusion n'a lieu que lorsque
toutes les protections de branche sont satisfaites.
Rejouer les digests d'images
Section intitulée « Rejouer les digests d'images »Les images de base méritent une mention séparée, parce que leur mode de défaillance est le plus déroutant : la CI tombe sans qu'aucune ligne du dépôt n'ait changé.
FROM python:3.11-slim@sha256:9534e5a8e315485d4061ed659af0fd78a284c015f9b73661b41d6bab25604534Ce digest est immuable, donc reproductible, donc jamais corrigé. Pendant ce temps, la base de vulnérabilités de votre scanner est mise à jour quotidiennement. Un job configuré ainsi finira par échouer :
with: severity: HIGH,CRITICAL ignore-unfixed: true exit-code: "1"Le réglage ignore-unfixed: true est pourtant le bon : il ne signale que les
vulnérabilités pour lesquelles un correctif existe. Autrement dit, quand ce
job devient rouge, il vous dit quelque chose d'exact et d'actionnable : une
correction est disponible en amont et vous ne l'avez pas prise.
La remédiation est le rejeu de l'épinglage :
# Relever le digest courant du tag suividocker buildx imagetools inspect python:3.11-slim --format '{{.Manifest.Digest}}'-
Relever le digest courant du tag que vous suivez.
-
Remplacer le digest dans tous les stages du
Dockerfile, y compris le stage de build : unFROMoublié laisse la vulnérabilité dans l'image intermédiaire. -
Laisser la CI trancher. Si le scan repasse au vert, la CVE venait bien de la couche de base. S'il reste rouge, elle vient de vos dépendances applicatives, et c'est un autre chantier.
La cadence, seule chose qui tienne dans la durée
Section intitulée « La cadence, seule chose qui tienne dans la durée »Le mécanisme importe moins que le rendez-vous. Trois formats fonctionnent, par ordre de coût croissant :
- L'auto-fusion des patchs ne coûte aucun temps humain, à condition que la CI soit un vrai garde-fou.
- Un créneau hebdomadaire de quinze minutes suffit à vider une file groupée. C'est le format qui échoue le plus souvent, parce qu'il repose sur la discipline.
- Une revue mensuelle rattrape les majeures et les changements de fond, avec lecture des changelogs.
Le signal d'alarme est simple à surveiller, et il est objectif :
# Nombre de pull requests Dependabot en attentegh pr list --repo OWNER/REPO --author "app/dependabot" --json number --jq 'length'Au-delà de cinq, la file n'est plus traitée, elle est subie. C'est le moment de grouper davantage, d'automatiser les patchs, ou d'assumer que certaines mises à jour n'ont pas besoin d'être proposées chaque semaine.
Contrôle de connaissances
Section intitulée « Contrôle de connaissances »Vérifiez que l'essentiel de ce guide est acquis. Les questions portent uniquement sur ce qui vient d'être expliqué ici.
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
Informations
- Le chronomètre démarre au clic sur Démarrer
- Questions à choix multiples, vrai/faux et réponses courtes
- Vous pouvez naviguer entre les questions
- Les résultats détaillés sont affichés à la fin
Lance le quiz et démarre le chronomètre
Vérification
(0/0)Profil de compétences
Quoi faire maintenant
Ressources pour progresser
Des indices pour retenter votre chance ?
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications
À retenir
Section intitulée « À retenir »- Un SHA épinglé ne reçoit aucun correctif : sans mécanisme de mise à jour, l'épinglage transforme une protection en dette.
- Le commentaire de version après le SHA n'est pas décoratif, c'est ce que Dependabot lit pour comparer.
- Déclarez l'écosystème
dockeren plus degithub-actions: sinon l'image de base reste figée et finit par faire échouer votre scan. - Le groupement et la fenêtre de quarantaine rendent la file traitable, et la quarantaine évite d'être dans la première vague d'adoption d'un paquet compromis.
- Renovate apporte
pinDigests, utile pour épingler et maintenir ce qui ne l'est pas encore ; Dependabot suffit sur un dépôt unique. - L'auto-fusion des patchs n'est défendable que si la CI est réellement bloquante, et
gh pr merge --auton'outrepasse aucune protection. - Une pull request Dependabot fermée à la main ne revient pas : il faut
@dependabot reopen. - Un scan d'image qui devient rouge sans changement dans le dépôt signale un correctif disponible en amont, pas un faux positif : rejouez le digest.
Pour aller plus loin
Section intitulée « Pour aller plus loin »- Auditer avec zizmor : Le scanner qui repère les actions restées sur un tag mutable, et celles dont le commentaire de version ne correspond plus au SHA.
- Durcir le runner avec Harden-Runner : La couche qui limite ce qu'une dépendance compromise peut exfiltrer, quand elle passe malgré la quarantaine.
- Checklist sécurité : Le point de contrôle qui vérifie que la file de mises à jour est réellement traitée, et pas seulement configurée.