flawopen.com/Sécurité GitHub Actions/Injection de scripts dans les workflows
Comment survient une injection de script GitHub Actions et comment l’éviter ?
Un workflow peut transformer une donnée en syntaxe shell en insérant un titre d’issue ou un champ de pull request dans le script avant le démarrage de Bash. Comme une imprimante de badges qui prend un nom pour une consigne. Passez la valeur par une variable d’environnement et mettez son expansion entre guillemets lorsqu’elle sert de donnée : Bash la reçoit séparément du script. L’impact dépend toujours du jeton, des secrets, du runner et de l’événement.
${{ ... }} avant le lancement du shell. Dans un bloc run:, l’entrée peut ainsi s’insérer dans le code du script.env: la transmet comme donnée de processus. Mettez l’expansion shell entre guillemets et évitez eval et les scripts construits dynamiquement.Cause racine : les données sont insérées avant l’analyse shell
GitHub développe les expressions avant de lancer le shell d’une étape run. Si un titre non fiable est interpolé dans le script, ses caractères peuvent modifier le programme shell au lieu de rester des données. Une valeur transmise par env: reste séparée du texte du script ; entre guillemets, son expansion reste un argument pour les commandes ordinaires. Cela ne sécurise pas un usage ultérieur avec eval, un autre interpréteur ou un outil qui traite les arguments comme du code. GitHub considère les champs d’événement non fiables comme contrôlables par un attaquant.
# RISQUÉ : les données de l’événement entrent dans le script shell généré
name: Issue Triage
on:
issues:
types: [opened]
permissions:
contents: read
jobs:
triage:
runs-on: ubuntu-latest
steps:
- name: Print issue title
run: |
printf 'Title: %s\n' "${{ github.event.issue.title }}"
# Plus sûr : transmettre la valeur de l’événement par l’environnement
name: Issue Triage
on:
issues:
types: [opened]
permissions:
contents: read
jobs:
triage:
runs-on: ubuntu-latest
steps:
- name: Print issue title
env:
ISSUE_TITLE: ${{ github.event.issue.title }}
run: |
printf 'Title: %s\n' "$ISSUE_TITLE"
Chemin d’attaque résumé
Un utilisateur contrôle un champ d’événement
Par exemple, le titre d’une issue publique, d’une pull request ou un nom de branche devient une entrée du workflow.
Le workflow l’insère dans le code shell
Une expression directe ${{ github.event... }} dans run: est évaluée avant l’analyse du script par Bash.
Le shell interprète le programme modifié
Si la valeur modifie la syntaxe, des commandes peuvent s’exécuter sous l’identité du processus du job. Si elle reste une donnée utilisée comme argument entre guillemets, cette injection ne se produit pas.
Les permissions du job définissent l’impact
Un job compromis n’accède qu’aux ressources exposées à cette exécution : permissions effectives de GITHUB_TOKEN, secrets fournis et ressources du runner. Examinez attentivement les événements d’issue et pull_request_target.
Liste de durcissement
- ✓N’interpolez jamais directement des valeurs non fiables de
github.eventdans un scriptrun:. Transmettez-les parenv:et utilisez des expansions entre guillemets comme"$ISSUE_TITLE". - ✓Gardez ces valeurs hors de
eval, des scripts générés, des chaînes de commandes shell et des outils qui interprètent les arguments comme du code ou des options. - ✓Définissez des
permissions:restrictives au niveau du workflow ou du job ; n’accordez l’écriture qu’au job qui en a besoin. - ✓Traitez
pull_request_targetetworkflow_runcomme des frontières privilégiées. N’extrayez, ne construisez et n’exécutez aucun code ou artefact non fiable dans ce contexte. - ✓N’écrivez pas de données multilignes non fiables dans
GITHUB_ENVouGITHUB_PATH. GitHub interdit d’écraserGITHUB_*etRUNNER_*, mais d’autres valeurs peuvent affecter les étapes suivantes. - ✓Épinglez les actions tierces à des SHA complets vérifiés, utilisez des runners isolés et éphémères pour les jobs non fiables et activez CodeQL pour les workflows Actions.
Sources primaires
- GitHub Docs — injections de scripts
- GitHub Docs — référence d’utilisation sécurisée
- GitHub Docs — utilisation sûre de pull_request_target
- GitHub Docs — commandes de workflow et GITHUB_ENV
- GitHub Docs — permissions de GITHUB_TOKEN