yaml.github-actions.security.pull-request-target-code-checkout.pull-request-target-code-checkout

profile photo of semgrepsemgrep
Author
76
Download Count*

This GitHub Actions workflow file uses pull_request_target and checks out code from the incoming pull request. When using pull_request_target, the Action runs in the context of the target repository, which includes access to all repository secrets. Normally, this is safe because the Action only runs code from the target repository, not the incoming PR. However, by checking out the incoming PR code, you're now using the incoming code for the rest of the action. You may be inadvertently executing arbitrary code from the incoming PR with access to repository secrets, which would let an attacker steal repository secrets. This normally happens by running build scripts (e.g., npm build and make) or dependency installation scripts (e.g., python setup.py install). Audit your workflow file to make sure no code from the incoming PR is executed. Please see https://securitylab.github.com/research/github-actions-preventing-pwn-requests/ for additional mitigations.

Run Locally

Run in CI

Defintion

rules:
  - id: pull-request-target-code-checkout
    languages:
      - yaml
    message: This GitHub Actions workflow file uses `pull_request_target` and checks
      out code from the incoming pull request. When using `pull_request_target`,
      the Action runs in the context of the target repository, which includes
      access to all repository secrets. Normally, this is safe because the
      Action only runs code from the target repository, not the incoming PR.
      However, by checking out the incoming PR code, you're now using the
      incoming code for the rest of the action. You may be inadvertently
      executing arbitrary code from the incoming PR with access to repository
      secrets, which would let an attacker steal repository secrets. This
      normally happens by running build scripts (e.g., `npm build` and `make`)
      or dependency installation scripts (e.g., `python setup.py install`).
      Audit your workflow file to make sure no code from the incoming PR is
      executed. Please see
      https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
      for additional mitigations.
    metadata:
      category: security
      owasp:
        - A01:2021 - Broken Access Control
      cwe:
        - "CWE-913: Improper Control of Dynamically-Managed Code Resources"
      references:
        - https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
        - https://github.com/justinsteven/advisories/blob/master/2021_github_actions_checkspelling_token_leak_via_advice_symlink.md
      technology:
        - github-actions
      subcategory:
        - audit
      likelihood: LOW
      impact: MEDIUM
      confidence: LOW
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - Code Injection
    patterns:
      - pattern-either:
          - pattern-inside: |
              on:
                ...
                pull_request_target: ...
                ...
              ...
          - pattern-inside: |
              on: [..., pull_request_target, ...]
              ...
          - pattern-inside: |
              on: pull_request_target
              ...
      - pattern-inside: |
          jobs:
            ...
            $JOBNAME:
              ...
              steps:
                ...
      - pattern: |
          ...
          uses: "$ACTION"
          with:
            ...
            ref: $EXPR
      - metavariable-regex:
          metavariable: $ACTION
          regex: actions/checkout@.*
      - metavariable-pattern:
          language: generic
          metavariable: $EXPR
          patterns:
            - pattern: ${{ github.event.pull_request ... }}
    severity: WARNING

Examples

pull-request-target-code-checkout.test.yaml

# cf. https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
# INSECURE. Provided as an example only.
on:
  pull_request_target:
  pull_request:

jobs:
  build:
    name: Build and test
    runs-on: ubuntu-latest
    steps:
      # ruleid: pull-request-target-code-checkout
      - uses: actions/checkout@v2
        with:
          ref: ${{ github.event.pull_request.head.sha }}

      - uses: actions/setup-node@v1
      - run: |
          npm install
          npm build

      - uses: completely/fakeaction@v2
        with:
          arg1: ${{ secrets.supersecret }}

      - uses: fakerepo/comment-on-pr@v1
        with:
          message: |
            Thank you!

  build2:
    name: Build and test 2
    runs-on: ubuntu-latest
    steps:
      # ruleid: pull-request-target-code-checkout
      - uses: actions/checkout@v2.3.4
        with:
          ref: ${{ github.event.pull_request.head.sha }}

      - uses: actions/setup-node@v1
      - run: |
          npm install
          npm build

      - uses: completely/fakeaction@v2
        with:
          arg1: ${{ secrets.supersecret }}

      - uses: fakerepo/comment-on-pr@v1
        with:
          message: |
            Thank you!

  this-is-safe-because-no-checkout:
    name: Echo
    runs-on: ubuntu-latest
    steps:
      # ok: pull-request-target-code-checkout
      - name: echo
        run: |
          echo "Hello, world"

  # cf. https://github.com/justinsteven/advisories/blob/master/2021_github_actions_checkspelling_token_leak_via_advice_symlink.md
  spelling:
    name: Spell checking
    runs-on: ubuntu-latest
    steps:
      # ruleid: pull-request-target-code-checkout
      - name: checkout-merge
        if: contains(github.event_name, 'pull_request')
        uses: actions/checkout@v2
        with:
          ref: refs/pull/${{github.event.pull_request.number}}/merge