Skip to main content
Skip to content

Utilisation sécurisée de pull_request_target

Découvrez les risques de sécurité de l’événement pull_request_target .

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 les protections qui GitHub s’appliquent à ces risques par défaut et comment refuser ces protections si nécessaire.

Risques de pull_request_target

Les flux de travail déclenchés par pull_request_target s’exécutent avec un niveau de confiance élevé : la tâche reçoit le GITHUB_TOKEN du dépôt de base ainsi qu’un accès aux secrets du dépôt et de l’organisation. Cela correspond au même niveau de confiance accordé à des événements comme push, qui ne peuvent être déclenchés que par des collaborateurs, et c'est ce qui rend pull_request_target utile pour l'automatisation réagissant aux pull requests provenant de forks, par exemple pour l'étiquetage, le tri ou l'envoi 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. 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 définissent actions/checkout sur la tête de la pull request au lieu de la branche par défaut, ce qui est non 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 provenant de la tête 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 dépôt principal.

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évention des demandes pwn à partir de GitHub Security Lab. Les formes vulnérables courantes sont les suivantes :

  • Extraction de la tête ou du 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 compilation, test ou exécution du 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 s'exécutant avec 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 ou non 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évention des demandes pwn à partir de GitHub Security Lab.

  • Le code extrait est-il 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 pull_request_target flux de travail

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. Pour réduire le risque d’empoisonnement du cache, les flux de travail déclenchés par pull_request_target ont un accès en lecture seule au cache dans le périmètre de la branche par défaut. Ces flux de travail peuvent restaurer des entrées de cache existantes, mais ne peuvent pas les créer ou les remplacer, de sorte qu’ils ne peuvent pas affecter l’exécution d’autres flux de travail, non liés, via le cache partagé. Si un tel flux de travail tente d’enregistrer un cache, l’enregistrement échoue, mais l’étape et le travail continuent, et l’échec est signalé comme un avertissement dans le journal de flux de travail. Si votre flux de travail doit remplir le cache, enregistrez-le à partir d’un flux de travail qui s’exécute sur un déclencheur approuvé tel que push. Pour plus d’informations, consultez « Référence sur la mise en cache des dépendances ».

  • 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 exécutions GitHub Actions. Pour plus d’informations, consultez « Informations de référence sur l’utilisation sécurisée ».

  • 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 passé en revue 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 vous soustraire à la .

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.