github-actions-hardening

Par github · awesome-copilot

Réviseur de renforcement de sécurité pour les fichiers de workflow GitHub Actions (`.github/workflows/*.yml`). Raisonne sur le modèle de menace propre à Actions que les outils de correspondance de motifs et les linters généralistes manquent — injection de script via des entrées non fiables, triggers privilégiés exécutant du code de fork, références d'actions mutables, et tokens avec des périmètres trop larges. Utilise cette skill lorsqu'on te demande de revoir, auditer, renforcer ou sécuriser un workflow GitHub Actions, lors de l'écriture d'un nouveau workflow, ou pour toute demande du type « ce workflow est-il sûr ? », « audite mon CI pour des problèmes de sécurité », « pourquoi `pull_request_target` est-il dangereux ici ? », « épingle mes actions », ou « restreins les permissions du `GITHUB_TOKEN` ». Couvre l'injection de script via l'interpolation `${{ }}`, l'escalade de privilèges via `pull_request_target` / `workflow_run`, l'épinglage par SHA des actions tierces, le principe du moindre privilège sur les permissions, l'injection via `GITHUB_ENV`/`GITHUB_OUTPUT`, l'exposition des secrets, l'OIDC comme alternative aux credentials de longue durée, et l'exposition des runners auto-hébergés sur les dépôts publics.

npx skills add https://github.com/github/awesome-copilot --skill github-actions-hardening

Durcissement des GitHub Actions

Un examinateur de sécurité spécialisé pour les workflows GitHub Actions. Il raisonne sur le modèle de menace spécifique aux Actions — où les limites de confiance vivent dans les types de déclencheur, les périmètres de token et l'interpolation de chaînes — plutôt que sur les vulnérabilités du code applicatif qu'un scanner de sécurité généraliste cherche. La plupart des risques de workflow sont invisibles aux linters de langage car le code dangereux c'est le YAML lui-même et la manière dont GitHub développe les expressions ${{ }} dans un shell avant que votre script ne s'exécute.

Quand utiliser cette compétence

Utilisez cette compétence quand la demande concerne :

  • L'examen, l'audit ou le durcissement de tout fichier dans .github/workflows/
  • L'écriture d'un nouveau workflow et vouloir qu'il soit sécurisé par défaut
  • Un workflow utilisant les déclencheurs pull_request_target, workflow_run ou issue_comment
  • Des questions sur les permissions GITHUB_TOKEN ou la clé permissions:
  • L'épinglage d'actions sur des SHAs de commit plutôt que des tags ou branches
  • La gestion d'entrées non fiables (titres de problèmes, corps de PR, noms de branches, messages de commit) dans des étapes run:
  • OIDC / authentification cloud depuis Actions, ou gestion des secrets en CI
  • Les runners auto-hébergés sur des repositories publics
  • Toute demande du type « ce workflow est-il sûr ? », « sécurisez mon CI », ou « examinez cette GitHub Action »

L'idée centrale

Dans un workflow, ${{ <expr> }} est développé par le runner dans le script avant que le shell ne l'exécute. Donc une étape comme :

- run: echo "Title: ${{ github.event.issue.title }}"

ne passe pas une variable — elle colle du texte contrôlé par l'attaquant directement dans votre commande shell. Un problème intitulé "; <attacker-command> # est concaténé dans le script et exécuté. Ce seul mécanisme est la vulnérabilité la plus courante des Actions dans le monde réel, et les modèles la génèrent régulièrement. Traitez chaque ${{ }} contenant des données qu'un contributeur externe peut influencer comme un puits d'injection de code.

Flux d'exécution

Suivez ces étapes dans l'ordre pour chaque workflow examiné.

Étape 1 — Cartographier les déclencheurs et le niveau de confiance

Lisez chaque déclencheur on: et classifiez le privilège du workflow :

  • push, pull_request (du même repo) → s'exécute avec la confiance du contributeur lui-même
  • pull_request depuis un fork → s'exécute avec un token en lecture seule, sans secrets (sûr par conception)
  • pull_request_target, workflow_run, issue_comment, issues → s'exécutent dans le contexte du repository de base avec un token lecture/écriture et accès complet aux secrets, mais peuvent être déclenchés par des contributeurs externes. Ce sont les déclencheurs dangereux.

Lisez references/triggers-and-privilege.md pour la matrice de confiance complète.

Étape 2 — Chercher les injections de script

Pour chaque bloc run:, chaque script: dans actions/github-script et chaque entrée d'une action personnalisée, listez les expressions ${{ }} et vérifiez si l'une se résout en données contrôlables par l'attaquant. Les contextes à haut risque incluent :

  • github.event.issue.title, github.event.issue.body
  • github.event.pull_request.title, github.event.pull_request.body, .head.ref, .head.label
  • github.event.comment.body, github.event.review.body
  • github.event.pages.*.page_name, github.event.commits.*.message, github.event.head_commit.*
  • github.head_ref et tout champ github.event.* qu'un auteur de fork peut définir

Lisez references/injection.md pour la liste complète des puits et les correctifs de motif sûr.

Étape 3 — Vérifier que les déclencheurs privilégiés n'exécutent pas du code non fiable

Si un workflow pull_request_target ou workflow_run vérifie le code PR/fork (ref: ${{ github.event.pull_request.head.sha }}) puis l'exécute (construction, tests, scripts d'installation, npm install avec scripts de cycle de vie, etc.), c'est une exécution de code distant contre un token privilégié. Signalez-le comme CRITIQUE. Le motif sûr est de diviser en deux workflows : un workflow pull_request non privilégié qui exécute le code non fiable, et un workflow workflow_run privilégié qui consomme uniquement ses résultats.

Étape 4 — Auditer permissions:

  • S'il n'y a pas de bloc permissions:, le workflow hérite de la valeur par défaut du repository, qui peut être lecture/écriture sur tout. Signalez-le.
  • Recommandez un permissions: {} au niveau supérieur (refus global) ou contents: read, puis accordez le minimum par job (par ex. pull-requests: write uniquement sur le job qui commente).
  • Signalez tout permissions: write-all ou des périmètres write larges que les étapes n'utilisent pas réellement.

Lisez references/permissions-and-tokens.md pour les conseils par périmètre et la configuration OIDC.

Étape 5 — Auditer les références d'actions (chaîne d'approvisionnement)

Pour chaque uses: :

  • Les actions tierces (pas actions/* ou github/*) DOIVENT être épinglées sur un SHA de commit complet de 40 caractères, pas une tag ou branche. Les tags et branches sont mutables ; une action upstream compromise peut réécrire v1 en code malveillant qui s'exécute avec votre token et vos secrets.
  • Les actions/* propriétaires sont à risque plus faible mais l'épinglage SHA est toujours la recommandation durcie.
  • Signalez @main, @master ou toute référence de branche comme HAUTE — c'est le « dernier » et peut changer à tout moment.
  • Notez la version lisible par l'humain dans un commentaire de fin : uses: foo/bar@<sha> # v2.1.0.

Lisez references/supply-chain.md pour l'épinglage, Dependabot pour les actions, et les risques d'artefacts/cache.

Étape 6 — Vérifier la gestion des secrets et des sorties

  • Pas de secrets affichés, imprimés ou écrits dans les logs ; pas de set -x / bash -x dans les étapes qui touchent aux secrets.
  • Les secrets ne doivent pas être passés aux étapes qui exécutent du code non fiable ou aux actions tierces non fiables.
  • Les données multilignes non fiables écrites dans $GITHUB_ENV ou $GITHUB_OUTPUT peuvent injecter des variables d'environnement ou des sorties d'étapes — utilisez la forme heredoc avec délimiteur aléatoire et ne jamais écrire l'entrée utilisateur brute.
  • actions/checkout laisse un token sur le disque par défaut ; définissez persist-credentials: false quand le job exécute plus tard du code non fiable.

Étape 7 — Produire le rapport

Affichez les résultats en utilisant le format dans references/report-format.md : d'abord un tableau résumé de sévérité, puis les résultats groupés avec le fichier, le YAML exact offensant, le risque en anglais simple, et un correctif concret avant/après. Ne jamais appliquer les changements automatiquement — présentez-les pour examen.

Guide de sévérité

Sévérité Signification Exemple
🔴 CRITIQUE Vol de token/secret ou RCE accessible par un contributeur externe pull_request_target vérifiant et exécutant du code fork ; ${{ github.event.* }} dans un run: sur un déclencheur privilégié
🟠 HAUTE Problème de chaîne d'approvisionnement ou de périmètre exploitable Action tierce sur une tag/branche mutable ; permissions write-all ; puits d'injection sur issue_comment
🟡 MOYEN Risque sous conditions ou enchaînement Bloc permissions: manquant ; secret accessible par un auteur de PR non-fork
🔵 BAS Lacune de durcissement, risque direct faible Action propriétaire non épinglée SHA ; persist-credentials laissé par défaut sur un job non privilégié
⚪ INFO Observation, pas une vulnérabilité Commentaire de version manquant à côté d'un SHA épinglé

Règles de sortie

  • Toujours montrer d'abord un tableau résumé des résultats (comptages par sévérité).
  • Grouper par type de problème, pas par fichier.
  • Être exact — citer la ligne offensante et donner la localisation de la ligne.
  • Toujours coupler chaque CRITIQUE/HAUTE avec un snippet YAML corrigé concret.
  • Ne jamais prétendre qu'un pull_request de fork est dangereux juste parce qu'il exécute du code non fiable — il n'a pas de secrets et un token en lecture seule. Réservez CRITIQUE aux déclencheurs privilégiés.
  • Si le workflow est déjà durci, dites-le et listez ce qui a été vérifié.

Fichiers de référence

Chargez-les au besoin :

  • references/triggers-and-privilege.md — Matrice de confiance pour chaque déclencheur, pourquoi pull_request_target et workflow_run sont privilégiés, et le motif de deux workflows sûrs.
    • Motifs de recherche : pull_request_target, workflow_run, issue_comment, fork, secrets, read-only token, trust boundary
  • references/injection.md — Liste complète des contextes ${{ }} contrôlables par l'attaquant et le motif sûr de variable env: pour chaque puits (run, github-script, entrées d'action).
    • Motifs de recherche : script injection, github.event, head_ref, issue title, env, intermediate variable, actions/github-script
  • references/permissions-and-tokens.md — Périmètres de GITHUB_TOKEN, recettes permissions: de moindre privilège par type de job, et OIDC pour l'authentification cloud au lieu de secrets de longue durée.
    • Motifs de recherche : permissions, GITHUB_TOKEN, write-all, contents: read, id-token, OIDC, least privilege
  • references/supply-chain.md — Épinglage SHA des actions tierces, Dependabot pour github-actions, intoxication d'artefacts et de cache sur workflow_run, et exposition des runners auto-hébergés.
    • Motifs de recherche : SHA pin, uses, mutable tag, Dependabot, download-artifact, cache, self-hosted runner
  • references/report-format.md — Modèle de sortie : tableau résumé, cartes de résultats, et blocs de remédiation avant/après.
    • Motifs de recherche : report, format, finding, summary, remediation, before, after

Skills similaires