D-OPEN

Comment securiser vos GitHub Actions contre les attaques supply chain en 6 etapes

Securiser GitHub Actions supply chain guide
Clara Vandenberg

Clara Vandenberg

Ingenieure securite DevOps et formatrice open source · 18 mai 2026 · 11 min de lecture

TL;DR

  • 96% des depots GitHub ne pinent pas leurs actions par SHA de commit — un vecteur d'attaque supply chain majeur.
  • 6 etapes concretes pour securiser vos workflows : eliminer pull_request_target, pinner par SHA, permissions minimales, OIDC, Zizmor, canary tokens.
  • Chaque etape est applicable en moins d'une heure — aucune refonte d'architecture necessaire.

Les attaques supply chain ciblant les pipelines CI/CD ont explose en 2025-2026. L'incident Grafana Labs de mai 2026 — ou un workflow pull_request_target mal configure a permis le vol du code source complet — n'est que le dernier exemple d'une tendance alarmante. Avant cela, l'incident Mini Shai-Hulud sur TanStack a compromis 169 paquets npm et 518 millions de telechargements.

La bonne nouvelle : securiser vos GitHub Actions ne necessite pas une refonte complete de votre infrastructure. Ce guide presente 6 etapes concretes, applicables en une journee, pour durcir significativement vos workflows contre les attaques supply chain les plus courantes. Chaque etape est independante — vous pouvez les appliquer dans l'ordre qui vous convient.

Etape 1 : Eliminer pull_request_target de vos workflows

Temps estime : 30 minutes

Le trigger pull_request_target est le vecteur d'attaque numero un sur les workflows GitHub Actions de projets open source. Contrairement a pull_request, il execute le workflow dans le contexte du depot cible avec acces complet aux secrets de production, meme quand la PR provient d'un fork externe non fiable.

Action immediate :

# Depuis la racine de votre depot
grep -r "pull_request_target" .github/workflows/

# Si vous trouvez des resultats, evaluez chaque workflow :
# 1. Le workflow a-t-il BESOIN d'acceder aux secrets ?
#    -> Si non, remplacez par pull_request
# 2. Le workflow execute-t-il du code du fork (checkout, eval) ?
#    -> Si oui, c'est une Pwn Request. Refactorisez.
# 3. Le workflow ne fait que labeler/commenter ?
#    -> OK mais isolez : pas de checkout du code PR

Pattern securise quand vous DEVEZ utiliser pull_request_target :

# SECURISE : le workflow ne checkout PAS le code du fork
on:
  pull_request_target:
    types: [opened, synchronize]

jobs:
  label:
    runs-on: ubuntu-latest
    permissions:
      pull-requests: write  # Permission specifique, pas "write-all"
    steps:
      # PAS de actions/checkout du fork ici
      - uses: actions/labeler@b4c85...  # Pinne par SHA
        with:
          repo-token: ${{ secrets.GITHUB_TOKEN }}

Pattern DANGEREUX a eliminer :

# DANGEREUX : checkout du fork avec acces aux secrets
on:
  pull_request_target:

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.event.pull_request.head.sha }}  # CODE DU FORK
      - run: npm test  # Execute du code non fiable AVEC secrets

Si votre workflow doit absolument executer du code de la PR avec des secrets, utilisez le pattern a deux workflows : un premier workflow pull_request qui execute les tests sans secrets, puis un second workflow workflow_run qui se declenche a la fin du premier et a acces aux secrets pour publier les resultats.

Etape 2 : Epingler toutes vos actions tierces par SHA de commit

Temps estime : 45 minutes

Un tag Git (@v4, @main) est mutable. Un mainteneur compromis — ou un attaquant qui prend le controle du depot de l'action — peut deplacer le tag vers un commit malveillant sans que votre workflow ne detecte le changement. Selon Wiz, seulement 3,9% des depots epinglent 100% de leurs actions par SHA.

Avant (vulnerable) :

- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: docker/build-push-action@v5

Apres (securise) :

- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11  # v4.1.7
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b  # v4.0.3
- uses: docker/build-push-action@4a13e500e55cf31b7a5d59a38ab2040ab0f42f56  # v5.1.0

Comment trouver le SHA d'un tag :

# Methode 1 : via l'API GitHub
gh api repos/actions/checkout/git/ref/tags/v4 --jq '.object.sha'

# Methode 2 : via git
git ls-remote https://github.com/actions/checkout.git v4

# Methode 3 : outil automatise (recommande)
# pin-github-action epingle automatiquement toutes vos actions
npx pin-github-action .github/workflows/*.yml

Astuce : ajoutez un commentaire avec le tag d'origine apres le SHA pour faciliter la maintenance. Quand une nouvelle version sort, vous saurez quelle version vous utilisez actuellement et pourrez decider de mettre a jour.

GitHub a annonce dans sa roadmap securite 2026 une section dependencies: qui verrouillera automatiquement les dependances par SHA. En attendant, le pinning manuel est votre meilleure protection.

Etape 3 : Configurer les permissions minimales par defaut

Temps estime : 20 minutes

Par defaut, le GITHUB_TOKEN dans un workflow a des permissions etendues. Si un workflow est compromis, l'attaquant herite de ces permissions. La solution : configurer permissions: read-all au niveau du workflow et n'accorder que les permissions specifiques necessaires a chaque job.

Configuration recommandee :

# Au niveau du fichier workflow (s'applique a tous les jobs)
permissions: read-all

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@b4ffde65...  # Lecture seule suffit
      - run: npm ci && npm test

  deploy:
    needs: build
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write        # Seulement ce job a besoin d'ecrire
      id-token: write        # Pour OIDC (etape 4)
    steps:
      - uses: actions/checkout@b4ffde65...
      - run: npm run build && npm publish

Configuration au niveau de l'organisation (recommande pour les equipes) :

Dans les parametres de votre organisation GitHub, sous Actions → General → Workflow permissions, selectionnez « Read repository contents and packages permissions ». Cela force permissions: read-all comme defaut pour tous les nouveaux workflows de l'organisation. Les workflows peuvent toujours demander des permissions supplementaires explicitement, mais le defaut securise empeche les oublis.

Etape 4 : Remplacer les secrets statiques par OIDC pour les acces cloud

Temps estime : 1 heure

Si vos workflows accedent a AWS, GCP ou Azure, vous stockez probablement des cles d'acces longue duree dans les secrets GitHub. Si un workflow est compromis (comme dans l'incident Grafana), ces cles sont exfiltrees. OIDC (OpenID Connect) elimine ce risque en generant des credentials ephemeres qui expirent apres quelques minutes.

Comment ca fonctionne :

  1. GitHub Actions genere un token JWT ephemere signe pour votre workflow specifique.
  2. Votre cloud provider verifie la signature et echange le token contre des credentials temporaires.
  3. Les credentials expirent automatiquement apres le run (typiquement 15-60 minutes).
  4. Meme si un attaquant exfiltre le token, il est inutilisable apres expiration et lie a un workflow specifique.

Exemple AWS (avant/apres) :

# AVANT : secret statique (dangereux)
- uses: aws-actions/configure-aws-credentials@v4
  with:
    aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
    aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

# APRES : OIDC (securise)
permissions:
  id-token: write    # Requis pour demander le token OIDC
  contents: read

- uses: aws-actions/configure-aws-credentials@e3dd6a42...  # v4, pinne SHA
  with:
    role-to-assume: arn:aws:iam::123456789012:role/github-actions-deploy
    aws-region: eu-west-3

Configuration cote AWS : creez un Identity Provider OpenID Connect dans IAM avec l'URL https://token.actions.githubusercontent.com et un role IAM avec une politique de confiance qui restreint l'acces a votre organisation, depot, et branche specifiques. Meme procedure pour GCP (Workload Identity Federation) et Azure (Federated Credentials).

Secrets statiques vs OIDC : surface d'attaque compareeSECRETS STATIQUES (dangereux)Cle AWS longue duree dans GitHub SecretsValide indefiniment si pas roteeExfiltrable via pull_request_targetReutilisable sans limite par l'attaquantOIDC (securise)Token JWT ephemere genere au runtimeExpire apres 15-60 minutes maxLie a un repo/branch/workflow specifiqueInutilisable apres expirationL'incident Grafana a expose des secrets statiques — avec OIDC, meme un workflow compromis ne peut pas voler de credentials durables

Etape 5 : Auditer vos workflows avec Zizmor en continu

Temps estime : 30 minutes

Zizmor est l'outil d'analyse statique open source que Grafana Labs a adopte et sponsorise apres l'incident de mai 2026. Developpe par William Woodruff, il detecte automatiquement les vulnerabilites les plus courantes dans les workflows GitHub Actions :

  • Triggers dangereux : pull_request_target avec checkout du fork
  • Actions non epinglees : utilisation de tags mutables au lieu de SHA
  • Injections de script : expressions ${{ }} non sanitisees dans les commandes run:
  • Permissions excessives : workflows sans declaration permissions:
  • Secrets exposes : patterns d'utilisation risquee des secrets

Installation et utilisation :

# Installation
pip install zizmor

# Audit de tous vos workflows
zizmor .github/workflows/

# Audit avec sortie SARIF (pour integration CI)
zizmor .github/workflows/ --format sarif > results.sarif

# Integration dans votre CI (meta : un workflow qui audite vos workflows)
# .github/workflows/security-audit.yml
name: Audit workflows
on: [push, pull_request]
permissions: read-all
jobs:
  zizmor:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@b4ffde65...
      - run: pip install zizmor
      - run: zizmor .github/workflows/ --format sarif > results.sarif
      - uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: results.sarif

Complement avec d'autres outils :

  • Trufflehog : scanne l'historique Git pour les secrets accidentellement commites
  • Gato-X : audite les permissions GitHub et detecte les escalades de privilege possibles
  • StepSecurity Harden-Runner : monitoring runtime des workflows (detecte les connexions reseau suspectes pendant l'execution)

Grafana a deploye les trois en complement de Zizmor. Pour un projet open source de taille moyenne, Zizmor seul couvre deja 80% des risques les plus critiques. Ajoutez les autres quand votre posture de securite de base est solide. Pour un guide plus large sur la securite de vos dependances, consultez notre article configurer Dependabot et Renovate pour l'audit de securite.

Etape 6 : Deployer des canary tokens et separer vos organisations

Temps estime : 45 minutes

Les cinq etapes precedentes sont preventives. L'etape 6 ajoute la detection — parce que meme la meilleure prevention peut echouer. C'est exactement ce qui a sauve Grafana : un canary token declenche par l'attaquant a immediatement alerte l'equipe securite.

Qu'est-ce qu'un canary token ? C'est un fichier piege place dans vos depots prives — un faux fichier .env, un faux credential AWS, un faux token API. Quand quelqu'un accede a ce fichier ou utilise ce credential, une alerte est immediatement envoyee. C'est un trip-wire numerique.

Deploiement :

# 1. Generez des canary tokens sur canarytokens.org ou thinkst.com
#    Types recommandes : AWS keys, GitHub token, fichier PDF/Word

# 2. Placez-les dans vos depots prives a des endroits strategiques :
#    - .env.production (faux, avec canary AWS keys)
#    - docs/internal/credentials.md (faux, avec canary tokens)
#    - config/secrets.yml (faux, avec canary API keys)

# 3. Ajoutez les fichiers dans .gitignore de vos vrais fichiers secrets
#    mais PAS les canary tokens - ils doivent etre accessibles

# 4. Configurez les alertes vers Slack/PagerDuty/email

Separation des organisations GitHub :

Grafana a separe son organisation open source de ses depots prives apres l'incident. C'est une pratique que nous recommandons pour toute organisation ayant a la fois des depots publics et prives :

  • Organisation publique (grafana) : depots open source, workflows CI publics, tokens avec permissions minimales.
  • Organisation privee (grafana-internal) : code proprietaire, secrets de production, workflows de deploiement.
  • Aucun token croise : un token compromis dans l'organisation publique ne peut jamais acceder aux depots de l'organisation privee.

Cette separation est le principe de compartmentalisation applique a GitHub. Un incident dans un compartiment ne se propage pas aux autres. C'est le meme principe qu'un sous-marin avec des compartiments etanches.

Les 6 etapes de securisation : votre checklist visuelle1Eliminer pull_request_targetRemplacer par pull_request30 min2Pinning SHA commitToutes actions tierces45 min3Permissions minimalespermissions: read-all defaut20 min4OIDC cloudEliminer secrets statiques1h5Audit Zizmor continuAnalyse statique CI/CD30 min6Canary + SeparationDetection et compartments45 minTOTAL : ~4 heures pour une posture solideApplicable sur n'importe quel projet GitHub Actions existant

Besoin d'aide pour securiser vos workflows ?

Nos experts appliquent ces 6 etapes sur vos depots en une demi-journee. Audit initial gratuit avec rapport Zizmor complet de vos workflows.

Demander un audit gratuit

Bonnes pratiques complementaires

Au-dela des 6 etapes fondamentales, voici des mesures supplementaires pour les organisations qui veulent aller plus loin :

Restreindre les actions autorisees au niveau de l'organisation : Dans les parametres GitHub de votre organisation, vous pouvez limiter les actions utilisables a une liste blanche. Seules les actions explicitement approuvees par votre equipe securite pourront etre utilisees dans les workflows. C'est contraignant mais c'est la methode la plus sure.

Activer le journal d'audit GitHub : Le journal d'audit de l'organisation enregistre toutes les modifications de workflows, les creations de secrets, et les changements de permissions. Configurez un export SIEM (Splunk, Datadog, ELK) pour avoir une visibilite temps reel sur les modifications de votre posture CI/CD.

Review obligatoire pour les modifications de workflows : Configurez une regie CODEOWNERS qui exige l'approbation de l'equipe securite pour toute modification dans .github/workflows/. C'est le meme principe que la code review pour le code de production — parce que vos workflows SONT du code de production.

# .github/CODEOWNERS
# L'equipe securite doit approuver toute modification de workflow
.github/workflows/ @your-org/security-team
.github/actions/   @your-org/security-team

Self-hosted runners isoles : Si vous utilisez des runners self-hosted, assurez-vous qu'ils sont ephemeres (detruits apres chaque job) et isoles du reseau de production. Un runner compromis qui a acces a votre reseau interne peut pivoter vers des systemes critiques. Pour un guide detaille sur le durcissement des runners, consultez notre article durcir les runners GitHub Actions self-hosted.

Les 5 erreurs les plus courantes a eviter

  1. Pinner les actions officielles mais pas les actions tierces. TOUTES les actions doivent etre pinnees par SHA, y compris celles de petits mainteneurs. Les attaquants ciblent les actions populaires mais peu maintenues.
  2. Utiliser permissions: write-all par paresse. Chaque permission accordee est une surface d'attaque supplementaire. Prenez 5 minutes pour identifier les permissions exactes dont chaque job a besoin.
  3. Stocker des secrets dans les variables d'environnement du workflow. Les variables d'environnement sont visibles dans les logs en cas d'erreur. Utilisez les GitHub Secrets et n'exposez-les qu'aux etapes specifiques qui en ont besoin.
  4. Ne pas auditer les workflows herites. Les workflows crees il y a deux ans par un developpeur qui a quitte l'equipe sont souvent les plus vulnerables. Auditez regulierement TOUS vos workflows, pas seulement les nouveaux.
  5. Faire confiance aux tags meme pour les actions officielles. L'action actions/checkout est maintenue par GitHub, mais le principe reste : un tag est mutable. Le pinning SHA est la seule garantie d'immutabilite.

Questions frequentes

Pourquoi epingler les GitHub Actions par SHA de commit plutot que par tag ?

Un tag Git est mutable : un mainteneur (ou un attaquant qui compromet le depot de l'action) peut deplacer un tag vers un commit malveillant sans que vous le sachiez. Un SHA de commit est immutable et cryptographiquement lie au contenu exact du code. Epingler par SHA garantit que le code execute dans votre CI est exactement celui que vous avez audite. Selon Wiz, seulement 3,9% des depots epinglent 100% de leurs actions par SHA, ce qui laisse 96% des projets vulnerables a ce vecteur d'attaque.

Qu'est-ce que Zizmor et comment l'utiliser pour auditer ses workflows ?

Zizmor est un outil d'analyse statique open source developpe par William Woodruff, specialise dans la detection de vulnerabilites dans les workflows GitHub Actions. Il detecte les triggers dangereux (pull_request_target), les actions non epinglees, les injections de script, les permissions excessives, et plus. Installation : pip install zizmor. Utilisation : zizmor .github/workflows/ depuis la racine de votre depot. Grafana Labs l'a adopte et sponsorise apres l'incident de mai 2026.

Comment OIDC remplace-t-il les secrets statiques dans GitHub Actions ?

OpenID Connect (OIDC) permet a GitHub Actions d'echanger un token d'identite ephemere contre des credentials cloud temporaires au moment de l'execution. Au lieu de stocker des cles AWS, GCP ou Azure longue duree dans les secrets GitHub (qui peuvent etre exfiltrees si un workflow est compromis), OIDC genere des credentials qui expirent apres quelques minutes. Configuration : activez le fournisseur d'identite GitHub dans votre cloud provider, configurez une politique de confiance, et utilisez l'action officielle (aws-actions/configure-aws-credentials avec role-to-assume).

Quels sont les triggers GitHub Actions les plus dangereux ?

Les triggers les plus dangereux sont : (1) pull_request_target, qui execute le workflow dans le contexte du depot cible avec acces aux secrets meme pour les PRs de forks externes. (2) workflow_run, qui peut etre chaine avec d'autres workflows pour escalader les privileges. (3) issue_comment avec des actions qui evaluent le contenu du commentaire, permettant l'injection de commandes. Le trigger le plus sur pour les PRs externes est pull_request, qui execute dans le contexte du fork sans acces aux secrets du depot cible.

Conclusion : 4 heures pour une posture de securite solide

Securiser vos GitHub Actions contre les attaques supply chain n'est pas un projet de transformation de 6 mois. C'est 4 heures de travail methodique qui reduisent drastiquement votre surface d'attaque. L'incident Grafana de mai 2026 a demontre que meme les projets les plus matures peuvent tomber sur un simple pull_request_target mal configure.

Les 6 etapes de ce guide couvrent les vecteurs d'attaque les plus exploites en 2025-2026. Elles sont independantes, incrementales, et applicables sans refonte d'architecture. Commencez par l'etape 1 (eliminer pull_request_target) et l'etape 2 (pinning SHA) — ces deux mesures seules bloquent la majorite des attaques documentees.

La securite CI/CD n'est plus un nice-to-have. C'est une obligation pour tout projet qui stocke des secrets, deploie en production, ou maintient du code que d'autres utilisent. Vos workflows GitHub Actions sont du code de production. Traitez-les comme tel.

Pret a securiser vos GitHub Actions ?

Notre equipe applique ces 6 etapes sur vos depots et forme vos developpeurs aux bonnes pratiques CI/CD. Audit initial gratuit avec rapport detaille.

Securiser mes workflows →