Audit des Workflows GitHub pour les Risques de Sécurité
Les attaques contre la chaîne d’approvisionnement ciblant GitHub Actions sont passées du stade théorique au stade courant. La compromission de tj-actions/changed-files en mars 2025 a démontré à quelle vitesse une seule action corrompue peut exposer des secrets dans des milliers de dépôts. Un an plus tard, le schéma s’est répété avec l’incident Trivy-action, où des attaquants ont effectué un force-push de code malveillant dans 76 des 77 tags de version.
Si vous avez déjà des workflows en production, cette liste de contrôle vous aide à identifier les failles les plus courantes sans avoir à repenser l’intégralité de votre pipeline.
Points Clés
- Définissez
permissions: {}au niveau du workflow et n’accordez que les portées minimales dont chaque job a besoin. - N’interpolez jamais les valeurs
${{ github.event.* }}directement dans des commandes shell — transmettez-les plutôt via des variables d’environnement. - Épinglez les actions tierces à des SHAs de commit complets et évitez de combiner
pull_request_targetavec des checkouts de code provenant de forks. - Remplacez les identifiants cloud statiques par OIDC, et empêchez les runners auto-hébergés d’exécuter du code non fiable dans les dépôts publics.
Vérifiez d’Abord les Permissions du GITHUB_TOKEN
Ouvrez n’importe quel fichier de workflow et examinez le bloc permissions de premier niveau. S’il est absent, les paramètres par défaut de votre organisation s’appliquent — et les organisations créées avant février 2023 ont souvent des droits en lecture-écriture par défaut.
La correction est simple :
permissions: {} # deny all at workflow level
jobs:
build:
permissions:
contents: read # grant only what the job needs
Définir permissions: {} au niveau du workflow vous oblige à déclarer explicitement ce dont chaque job a besoin. Un job qui se contente de lire du code ne devrait jamais disposer d’un GITHUB_TOKEN avec accès en écriture à votre dépôt.
Repérez les Entrées Non Fiables dans les Commandes Shell
Recherchez dans vos fichiers de workflow les occurrences de ${{ github.event à l’intérieur des blocs run:. Il s’agit du schéma d’injection de script le plus répandu :
# Risqué : l'attaquant contrôle le titre de la PR
- run: echo "Checking ${{ github.event.pull_request.title }}"
L’alternative sécurisée consiste à transmettre les valeurs non fiables via une variable d’environnement intermédiaire :
- name: Check PR title
env:
TITLE: ${{ github.event.pull_request.title }}
run: echo "Checking $TITLE"
La valeur est transmise via l’environnement plutôt qu’interpolée dans le script shell, ce qui empêche les métacaractères shell présents dans l’entrée de s’échapper et d’exécuter des commandes. Soyez également vigilant aux écritures dans GITHUB_ENV et GITHUB_PATH dans les étapes qui traitent du contenu contrôlé par l’utilisateur — les attaquants peuvent s’en servir pour injecter des variables d’environnement ou des binaires malveillants dans les étapes ultérieures.
Auditez l’Utilisation de pull_request_target
pull_request_target s’exécute avec accès aux secrets de la branche de base, ce qui le rend utile pour les workflows devant commenter des PRs issues de forks. Le risque ne vient pas du déclencheur lui-même, mais de sa combinaison avec un checkout du code du fork :
# Combinaison dangereuse
on: pull_request_target
jobs:
test:
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }} # runs attacker code
- run: npm test # with access to your secrets
Si vous utilisez pull_request_target, assurez-vous qu’aucune étape n’exécute du code provenant de la branche de la PR. GitHub a partiellement atténué ce risque fin 2025, mais ce déclencheur reste à haut risque lorsqu’il est combiné avec des checkouts de forks.
Discover how at OpenReplay.com.
Vérifiez l’Épinglage des Actions Tierces
La compromission de tj-actions/changed-files a fonctionné parce que les équipes référençaient des tags mutables comme @v35. Les valeurs des tags peuvent être réécrites silencieusement. L’épinglage à un SHA de commit complet empêche cela :
# Vulnérable
- uses: tj-actions/changed-files@v35
# Sécurisé
- uses: tj-actions/changed-files@d6babd6899969df1a11d14c368283ea4436bca78
GitHub propose désormais des politiques au niveau de l’organisation pour imposer l’épinglage par SHA et faire échouer les workflows utilisant des actions non épinglées. Consultez Settings → Actions → General au niveau de l’organisation. L’épinglage seul ne suffit pas — envisagez également un délai de 7 à 14 jours avant d’adopter de nouvelles versions d’actions, la plupart des compromissions de chaîne d’approvisionnement étant détectées en moins d’une semaine.
Évaluez l’Exposition des Runners Auto-Hébergés
Les runners auto-hébergés sont persistants par défaut. Un workflow compromis peut installer des backdoors qui survivent entre les jobs. La question critique est de savoir si des dépôts publics utilisent vos runners auto-hébergés — si c’est le cas, n’importe quel contributeur peut soumettre une PR qui exécute du code arbitraire sur votre infrastructure.
Vérifiez vos groupes de runners sous Settings → Actions → Runners et confirmez que les dépôts publics en sont exclus. Pour les charges de travail sensibles, privilégiez les runners just-in-time (JIT) qui sont détruits après chaque job.
Remplacez les Identifiants Cloud Statiques par OIDC
Si vos workflows s’authentifient auprès d’AWS, Azure ou GCP à l’aide d’identifiants statiques stockés en tant que secrets, ces identifiants sont exposés à chaque action et étape de ce job. OpenID Connect (OIDC) élimine ce problème en émettant des tokens de courte durée, limités au périmètre du job, au moment de l’exécution. Aucun secret à dérober, aucun identifiant à renouveler manuellement.
Vérifications Supplémentaires à Effectuer
- Gestion des artefacts : Définissez
persist-credentials: falsesuractions/checkoutsauf si les étapes suivantes ont explicitement besoin du token. Cela empêche le token de checkout de rester disponible dans la configuration Git locale pour les étapes ultérieures du workflow. - Protections d’environnement : Les secrets de déploiement doivent résider dans des GitHub Environments avec des validateurs requis, et non en tant que simples secrets de dépôt.
- Attestations d’artefacts : Pour les packages publiés, les attestations d’artefacts de GitHub fournissent un lien vérifiable entre un build et son workflow source.
- OpenSSF Scorecards : L’action Scorecards peut être configurée pour exécuter des vérifications automatisées des permissions de tokens, des actions épinglées et des injections de scripts — utile pour détecter automatiquement les régressions.
Par Où Commencer
Lancez une recherche dans .github/workflows/ pour ces schémas : blocs permissions absents ou définis sur write-all, ${{ à l’intérieur des étapes run:, déclencheurs pull_request_target, et références d’actions sans SHA complet. Ces quatre vérifications permettront de mettre en évidence les problèmes les plus critiques dans la plupart des dépôts, sans nécessiter de nouveaux outils.
Conclusion
Sécuriser GitHub Actions ne nécessite pas une réécriture complète du pipeline — la plupart des incidents réels sont liés à un petit ensemble d’erreurs récurrentes : portées de tokens trop larges, interpolation non sécurisée d’entrées non fiables, références d’actions mutables et runners exposés à du code non fiable. Parcourir les vérifications ci-dessus vous donne une base de référence solide. Complétez cette base avec une analyse automatisée via OpenSSF Scorecards ou un outil similaire, et vous détecterez les régressions avant qu’elles n’atteignent la production.
FAQ
La recherche de code GitHub prend en charge les requêtes à l'échelle de l'organisation. Recherchez des termes comme 'pull_request_target', 'permissions: write-all', ou 'github.event.pull_request.title' en ciblant le chemin path:.github/workflows. Pour une analyse plus approfondie, des outils comme Octoscan, zizmor et l'action OpenSSF Scorecards peuvent analyser des dépôts entiers et générer des rapports sur les portées de tokens, les actions non épinglées et les points d'injection automatiquement.
Non, mais cela rend les mises à jour explicites. Vous décidez quand mettre à jour le SHA après avoir examiné les différences entre les versions. Des outils comme Dependabot et Renovate peuvent ouvrir des pull requests qui mettent à jour les SHAs épinglés automatiquement, vous offrant la sécurité de l'épinglage sans la charge de maintenance. Un délai de 7 à 14 jours avant de fusionner ces mises à jour réduit davantage l'exposition aux versions fraîchement compromises.
Pour AWS, Azure, GCP et la plupart des principaux fournisseurs, oui. Les tokens OIDC sont de courte durée, limités à une exécution de workflow spécifique, et ne peuvent pas être exfiltrés pour une utilisation ultérieure. La configuration nécessite l'établissement d'une relation de confiance chez votre fournisseur cloud, mais élimine la charge de renouvellement et limite le rayon d'impact en cas de compromission d'un workflow. Les secrets statiques restent une solution de repli valable uniquement lorsque OIDC n'est pas pris en charge.
Le déclencheur pull_request s'exécute dans le contexte du fork et n'a pas accès aux secrets du dépôt de base, ce qui le rend sûr pour l'exécution de tests sur du code non fiable. Le déclencheur pull_request_target s'exécute dans le contexte du dépôt de base avec accès aux secrets, destiné à des tâches comme l'étiquetage des PRs. La combinaison dangereuse à éviter est l'utilisation de pull_request_target avec un checkout du code du fork.
Gain control over your UX
See how users are using your site as if you were sitting next to them, learn and iterate faster with OpenReplay. — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.