Skip to main content

Utilisation sécurisée de pull_request_target

En savoir plus sur les risques de sécurité du pull_request_target event.

Ce guide vous permet d’évaluer si votre flux de travail doit utiliser l’événement pull_request_target et comprendre les risques de sécurité impliqués. Il explique également que la protection GitHub s’applique à actions/checkout v7 et ultérieurement pour réduire ces risques par défaut, et quand refuser cette protection si nécessaire.

Lisez pull_request_target avant de récupérer le code d’une pull request dans l’un de ces workflows, ou avant de définir l’entrée allow-unsafe-pr-checkout dans actions/checkout.

Les risques de l’événement pull_request_target

Les flux de travail déclenchés par pull_request_target s’exécutent avec un niveau de confiance élevé : le job reçoit le GITHUB_TOKEN du dépôt de base, l’accès aux secrets du dépôt et de l’organisation, ainsi qu’un accès en écriture au cache de la branche par défaut. Il s’agit de la même confiance accordée aux événements tels que push, que seuls les collaborateurs peuvent déclencher, et c’est ce qui rend pull_request_target utile pour l’automatisation qui répond aux pull requests issues de forks, par exemple pour l’étiquetage, le triage ou la publication de vérifications d’état authentifiées.

Pour comprendre pourquoi cela est sûr par défaut, et comment cette sécurité est généralement rompue, examinez-la pull_request_target contre pull_request.

L’événement pull_request (ainsi que pull_request_review et pull_request_review_comment) est inhabituel : il exécute le fichier de workflow à partir du commit de fusion de la pull request. Pour une pull request ouverte à partir d’un fork, ce commit est contrôlé par une personne qui ne dispose pas d’un accès en écriture au dépôt de base. Pour exécuter en toute sécurité du code de workflow non approuvé, GitHub limite ces événements à un GITHUB_TOKEN en lecture seule, bloque l’accès aux autres secrets et applique des politiques d’approbation des forks afin d’éviter les abus de ressources de calcul. Pour plus d’informations, consultez « Événements qui déclenchent des flux de travail ». Par défaut, actions/checkout dans un workflow pull_request récupère également le commit de fusion de la pull request, afin que le code récupéré et le workflow exécuté soient cohérents.

pull_request_target apporte un changement important et subtil : le workflow, ainsi que tout appel ultérieur à actions/checkout qui ne spécifie pas de ref, provient de la branche par défaut du dépôt de base, et non de la pull request. Étant donné que seul le code fiable de la branche par défaut s’exécute, on peut accorder en toute sécurité des secrets et un jeton avec accès en lecture/écriture. Aucun code issu du fork n’est exécuté par défaut.

Vous introduisez un risque lorsqu’un auteur de flux de travail remplace cette valeur par défaut pour exécuter le code du fork. Les développeurs choisissent pull_request_target fréquemment parce qu’ils souhaitent exécuter la demande de tirage d’un fork via CI et avoir accès aux secrets, par exemple pour exécuter des tests qui ont besoin d’un registre privé. Pour ce faire, ils font pointer actions/checkout vers la référence HEAD de la pull request au lieu de la branche par défaut, ce qui n’est pas sécurisé :

# INSECURE. Provided as an example only.
on:
  pull_request_target:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
        with:
          ref: ${{ github.event.pull_request.head.sha }}
      - name: Test
        run: make test

L’étape de checkout à elle seule n’exécute pas de code non fiable. Le fichier de flux de travail lui-même provient toujours de la branche par défaut. La faille est rendue possible par l’étape next, qui exécute le code récupéré dans le répertoire de travail actuel. Ici, make test exécute une Makefile issue de la branche source de la pull request. Un attaquant n’a qu’à ouvrir une pull request à partir d’un fork dont le Makefile (ou le script de build, la commande de test, la dépendance ou le fichier de configuration) contient des commandes malveillantes. Ces commandes s’exécutent ensuite avec les secrets et le jeton du référentiel de base.

Ce modèle est appelé « demande pwn » et a été la cause racine de plusieurs compromis de chaîne d’approvisionnement. Pour plus d’informations, consultez Prévenir les demandes pwn à partir de GitHub Security Lab. Les formes vulnérables courantes sont les suivantes :

  • Extraire le commit HEAD ou le commit de fusion d’une pull request dans actions/checkout (ref: ${{ github.event.pull_request.head.sha }}, ref: refs/pull/${{ github.event.pull_request.number }}/merge), puis compiler, tester ou autrement exécuter le résultat.
  • Définir repository: sur le fork (repository: ${{ github.event.pull_request.head.repo.full_name }}) pour récupérer directement la branche du fork.
  • Récupération du code de la pull request en dehors de actions/checkout (par exemple avec git fetch, gh pr checkout ou en téléchargeant un artefact depuis l’exécution pull_request d’un fork), puis exécution de celui-ci.

Les requêtes Pwn ne sont pas non plus uniques à pull_request_target. Tout événement exécuté avec accès à des secrets peut introduire une pwn request s’il récupère, ou télécharge et exécute, du code non fiable. Par exemple, un workflow issue_comment ou workflow_run qui récupère et exécute le code d’une pull request provenant d’un fork est vulnérable de la même manière. Un workflow workflow_run doit traiter les artefacts téléversés par d’autres workflows comme des données non fiables, car leur contenu peut provenir d’un fork.

Décider s’il faut utiliser pull_request_target

Certains flux de travail doivent récupérer le code d’une pull request issue d’un fork avec un niveau de confiance élevé, et c’est pour cette raison que pull_request_target a été créé. Par exemple, la génération de rapports de couverture nécessitant un registre privé d’artefacts, ou la création et l’exécution de contrôles authentifiés sur les modifications apportées par la pull request. Tenez compte des questions ci-dessous avant d’utiliser pull_request_target ou de choisir l’indicateur allow-unsafe-pr-checkout dans actions/checkout.

  • Pouvez-vous utiliser pull_request à la place ? pull_request se déclenche sur les mêmes événements que pull_request_target et exécute le code de workflow à partir de la pull_request branche de fusion. Il le fait en toute sécurité sur les pull requests issues de forks, grâce aux protections détaillées ci-dessus. Si un accès secret supplémentaire n’est pas nécessaire, utilisez pull_request. Des flux de travail plus complexes peuvent être restructurés pour séparer la gestion potentiellement dangereuse du code de demande de tirage (pull request) de l’accès aux secrets. Pour plus d’informations, consultez Prévenir les requêtes malveillantes à partir de GitHub Security Lab.

  • Le code extrait est-il déjà exécuté ? Il s’agit de la faille à l’origine des vulnérabilités de type pwn request. Cela est le plus souvent introduit avec actions/checkout en récupérant la branche source d’une pull request dans le répertoire de travail, puis en l’exécutant. Sauf si l’entrée path est définie, actions/checkout écrit le code dans le $GITHUB_WORKSPACE répertoire, qui est généralement le répertoire de travail où les commandes suivantes s’exécutent. L’exécution n’est pas limitée à vos propres étapes : les commandes de génération et de test telles que npm install et npm run build, ainsi que les fichiers de configuration et les dépendances que le code apporte, peuvent tous exécuter du code contrôlé par l’attaquant. L’exécution ne nécessite pas d’étape de compilation explicite. Vous devez vous assurer que le code récupéré est uniquement inspecté comme des données et n’est jamais exécuté avant d’utiliser un événement pull_request_target.

Renforcement d’un flux de travail pull_request_target

Si vous avez confirmé que vous avez besoin pull_request_target, appliquez ces contrôles pour limiter l’impact de cet événement à haut risque. Celles-ci s’appliquent, que votre flux de travail récupère ou non le code de la pull request.

  • Restreindre les secrets. Vérifiez que les autorisations définies sur le GITHUB_TOKEN respectent le principe du moindre privilège et que seuls les secrets du dépôt et de l’organisation nécessaires sont utilisés pour le flux de travail. Pour plus d’informations, consultez « Utiliser GITHUB_TOKEN pour l’authentification dans les flux de travail ».

  • Comprendre l’impact de la mise en cache. En dehors de GITHUB_TOKEN et des secrets configurés, les workflows qui s’exécutent sur pull_request_target disposent également d’un accès en écriture au cache partagé avec d’autres workflows sur la branche par défaut. Les modifications malveillantes apportées à ce cache à partir d’événements pull_request_target peuvent avoir un impact sur l’exécution d’autres flux de travail non liés.

  • Vérifiez que le calcul sous-jacent est isolé et éphémère. Si des exécuteurs auto-hébergés sont utilisés, vous devez confirmer que l’environnement de l’exécuteur est correctement restreint à partir de ressources internes et n’est pas réutilisé entre les GitHub Actions exécutions. Pour plus d’informations, consultez « Informations de référence sur l’utilisation sécurisée ».

  • Le gate intervient après l’approbation. pull_request_target Les flux de travail peuvent être soumis à une validation obligatoire label, que seuls les utilisateurs disposant d’un accès en écriture peuvent ajouter. Ceci est détaillé dans les GitHub Security Lab prévention des demandes pwn.

  • Appliquez les meilleures pratiques de GitHub Actions sécurité. Outre les risques spécifiques liés aux requêtes pwn, d’autres vulnérabilités courantes, telles que l’injection de commandes, peuvent exister et affecter le code exécuté dans cet événement privilégié. Pour plus d’informations, consultez Sécurisation de vos GitHub Actions et workflows : données non fiables dans le GitHub Security Lab. Pour identifier les vulnérabilités courantes GitHub Actions et s’en protéger de manière proactive, activez CodeQL pour GitHub Actions. Pour plus d’informations, consultez « Définition de la configuration par défaut pour l’analyse du code ».

Désactivation des protections intégrées

Si vous avez examiné les questions ci-dessus et confirmé que votre flux de travail nécessite pull_request_target et l’utilise en toute sécurité, vous pouvez désactiver la protection actions/checkout. Définir allow-unsafe-pr-checkout: true comme entrée actions/checkout permet de récupérer les références HEAD des pull requests depuis des forks. Effectuez cette opération uniquement après avoir confirmé que le code extrait n’est jamais exécuté. L’entrée est intentionnellement nommée pour être facile à repérer dans la révision du code et l’analyse statique.

Cette protection ne couvre que les références de pull request de fork. L’extraction d’autres codes non approuvés, tels qu’un référentiel tiers non lié, l’extraction de code avec git fetch ou gh pr checkoutl’exécution d’un artefact téléchargé, n’est pas couverte par les actions/checkout vérifications.

Restriction de l’utilisation de pull_request_target

Les administrateurs de référentiel, d’organisation et d’entreprise peuvent utiliser des protections d’exécution de flux de travail pour contrôler quels événements et acteurs peuvent déclencher des flux de travail. Si un référentiel n’a pas d’utilisation légitime pour pull_request_target, le fait de le restreindre supprime le risque, quelle que soit la façon dont les flux de travail individuels sont écrits.