When using GitHub Actions, certain workflow triggers such as pull_request_target and workflow_run execute with the
repository’s privileges. This creates a security risk when these workflows check out code from a forked repository and then use this untrusted code as
input for subsequent steps.
If code from the fork is used as an input inside the workflow, they could exploit this to extract sensitive information, manipulate the repository,
or execute arbitrary commands with the permissions of the repository. Special considerations should be taken into account on organizations and
repositories created before 2023 when the default permissions of
the GITHUB_TOKEN were changed to read-only.
There is a risk if you answered yes to any of these questions.
If the flow does not require write access to the repository nor access to its secrets, the recommended approach is to avoid using triggers that cause execution using elevated privileges.
If this is not feasible, the workflow can be split into two parts:
pull_request that performs checks that do not require elevated permissions, andworkflow_run on completion of the first job, that performs the actions requiring elevated
permissionsWhen doing this, it is important to make sure that the privileged workflow does not process input from the untrusted workflow.
The following workflow executes the build.sh script from the fork using the privileges of the repository:
name: Example
on:
pull_request_target:
jobs:
main:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }} # Sensitive
- name: Build
run: |
./build.sh
If elevated permissions are not needed, the simplest way to fix this is to use pull_request as the trigger.
name: Example
on:
pull_request:
jobs:
main:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Build
run: |
./build.sh