CI/CD
Cache GitHub Actions : comment il fonctionne et ce qu'il cache
Le cache GitHub Actions conserve des fichiers d'une exécution de workflow à l'autre, pour que les jobs évitent les téléchargements déjà effectués. Il accélère les builds. Il signifie aussi que des paquets arrivent dans votre build sans être récupérés, ce que la plupart des enregistrements d'un build ne voient jamais.
Mis à jour le
Comment fonctionne le cache
L'action actions/cache enregistre un ensemble de chemins sous une clé à la fin d'un job et les restaure au
début d'un job ultérieur. Une configuration npm typique met en cache le cache de téléchargement du gestionnaire de paquets et fonde sa clé sur le lockfile :
- uses: actions/cache@v4
with:
path: ~/.npm
key: npm-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
restore-keys: |
npm-${{ runner.os }}-
- run: npm ci
À la restauration, l'action cherche d'abord une correspondance exacte avec key, puis une correspondance partielle, puis chaque
préfixe restore-keys tour à tour. Lorsque plusieurs caches correspondent à un préfixe, elle restaure le plus
récent. Ce repli maintient la rapidité des builds après une modification du lockfile, mais il signifie aussi qu'un job peut démarrer à partir d'un
cache construit pour un lockfile plus ancien.
Souvent, vous n'avez même pas besoin de l'action. setup-node, setup-python, setup-java,
setup-go, setup-ruby et setup-dotnet intègrent la mise en cache. Pour Node.js,
setup-node met en cache les données globales de paquets de npm, Yarn et pnpm, et non node_modules, et active
automatiquement le cache npm lorsque package.json déclare npm comme packageManager.
Portée et limites
| Règle | Ce que fait GitHub |
|---|---|
| Les caches qu'une exécution peut restaurer | Ceux de sa propre branche et de la branche par défaut ; pour les pull requests, aussi ceux de leur branche de base |
| Ce qu'une pull request peut écrire | Uniquement des caches limités à sa merge ref, pas à la branche par défaut |
| Stockage | 10 Go par dépôt par défaut ; les propriétaires d'organisation et d'entreprise peuvent augmenter cette limite |
| Éviction | Les entrées inutilisées depuis plus de 7 jours, et les moins récemment utilisées lorsque le stockage est plein |
| Secrets | Ne les mettez pas en cache : toute personne ayant accès aux pull requests peut lire le contenu du cache |
Ce que le cache dissimule à votre SBOM
Un cache est un raccourci qui contourne le registre de paquets. C'est tout son intérêt, et c'est aussi pourquoi il brouille tous les enregistrements de ce qu'un build a utilisé :
- Pas de téléchargement, pas de trace. Les paquets restaurés depuis un cache sont installés sans requête vers le registre. Un enregistrement construit à partir du trafic réseau du build les manque, sauf s'il suit le cache.
-
Un contenu ancien sous une nouvelle clé. Une correspondance partielle
restore-keysrestaure un cache construit pour un lockfile antérieur. L'installation ajoute ou remplace ensuite ce qui a changé, mais le point de départ du job n'est pas ce que décrit le lockfile actuel. - Plus que vos dépendances. Les caches contiennent aussi des outils de build, des compilateurs et des fichiers générés, qu'aucun manifeste d'application ne liste.
- Un scan ne peut pas le savoir. Une SBOM basée sur le lockfile décrit ce que dit le lockfile, que le job ait ou non installé exactement cela depuis son cache.
Pour replacer cela dans le problème plus large, voir pourquoi un lockfile n'est pas un enregistrement de ce qui a été livré et les dépendances transitives.
L'empoisonnement du cache
Les caches sont partagés entre les workflows d'un dépôt, ce qui en fait un passage de l'un à l'autre. En mai 2024, le chercheur en sécurité
Adnan Khan a montré que toute personne capable d'exécuter du code dans le contexte de la branche par défaut, via un
workflow pull_request_target vulnérable ou une dépendance compromise, peut écraser des fichiers dans les workflows
qui restaurent des caches. Avec le token de cache d'un job en cours, un attaquant peut remplir le cache du dépôt pour que
GitHub évince les entrées légitimes, puis écrire des entrées empoisonnées sous les mêmes clés. Un workflow de release qui les restaure
exécute les fichiers de l'attaquant avec ses propres secrets.
Pour réduire le risque :
- Construisez les releases à partir d'un état propre, ou de caches que seul le workflow de release écrit.
- N'exécutez jamais le code de pull requests non fiables dans un contexte de branche par défaut.
- Tenez les secrets et les tokens à l'écart des chemins mis en cache.
- Considérez ce qu'un cache a restauré comme une entrée du build qui mérite le même examen qu'un téléchargement.
Comment CRACI gère les caches
CRACI est un runner GitHub Actions : actions/cache et les caches setup-* fonctionnent donc comme
aujourd'hui, aux côtés de la mise en cache des couches de conteneur. La mise en cache explique aussi en partie pourquoi CRACI exécute les builds environ deux fois plus vite que les
runners hébergés par GitHub, avec un matériel plus rapide et des files d'attente plus courtes.
Ce qui change, c'est l'enregistrement. Le proxy de CRACI, qui comprend les paquets, enregistre les paquets récupérés par un job, et les preuves suivent les caches : lorsqu'un job restaure un cache, CRACI reporte les dépendances dont il a connaissance dans la SBOM de ce job.
- Une complétude par cache. Chaque cache a un état de complétude, comme chaque job. Un job qui restaure un cache incomplet obtient une SBOM incomplète, et un cache qu'il produit reporte ce statut : une lacune ne devient donc jamais silencieusement un enregistrement complet.
- Aucune déduction à partir de l'archive. CRACI ne lit pas les manifestes de paquets dans l'archive du cache. Il sait ce que contient un cache parce qu'il a enregistré le job qui l'a produit.
-
Un cache par job producteur garantit la fiabilité de ces preuves, avec une politique de trafic sortant réglée sur
default: denydans le job producteur. Le guide sur la complétude des caches et des SBOM donne les détails.
Voir les SBOM générées au build pour comprendre le fonctionnement de l'enregistrement, ou réservez une démo pour exécuter l'un de vos workflows avec cache sur CRACI.
Cache GitHub Actions : questions fréquentes
Combien de temps GitHub conserve-t-il un cache Actions ?
GitHub supprime les entrées de cache qui n'ont pas été utilisées depuis plus de 7 jours. Lorsqu'un dépôt dépasse sa limite de stockage, 10 Go par défaut, il évince aussi des caches selon leur dernier accès, en commençant par le plus ancien.
setup-node met-il node_modules en cache ?
Non. Le paramètre cache d'actions/setup-node met en cache les données globales de paquets du gestionnaire de paquets pour npm, Yarn ou pnpm, et non node_modules. L'étape d'installation s'exécute toujours, mais elle lit les paquets depuis le cache restauré au lieu de les télécharger.
Une pull request peut-elle lire les caches de la branche principale ?
Oui. Une exécution de workflow peut restaurer les caches de sa propre branche et de la branche par défaut, et une pull request peut aussi restaurer ceux de sa branche de base. Les caches créés dans une pull request sont limités à sa merge ref : ils ne peuvent donc pas être écrits dans la portée de la branche par défaut.
Le cache Actions est-il sûr dans les workflows de release ?
C'est un compromis. Des recherches publiées en 2024 ont montré que toute personne capable d'exécuter du code dans un workflow de la branche par défaut peut empoisonner des caches restaurés par d'autres workflows, y compris les workflows de release. Pour les workflows qui publient des releases ou détiennent des secrets de déploiement, il est plus sûr de construire à partir d'un état propre ou de caches qu'eux seuls écrivent.
Un cache restauré modifie-t-il ma SBOM ?
Il peut la modifier. Les paquets restaurés depuis un cache sont installés sans être téléchargés : un enregistrement construit à partir du trafic réseau les manque donc, sauf s'il suit le cache. Et un scan du lockfile ne vous dit pas si le cache contenait exactement ces versions.
Gardez vos caches et une SBOM complète
Exécutez votre workflow sur CRACI : les caches accélèrent toujours le build, et les dépendances qu'ils transportent restent dans la SBOM enregistrée de chaque job.
Réserver une démo