Insecure Pull Request Target
Insecure Pull Request Target
Description
pull_request_target runs with the base repository’s token (Usually write). If the workflow checks out the PR’s head commit, code from an untrusted fork executes with maintainer permissions—allowing attackers to steal secrets or push malicious commits. GitHub Security Lab explicitly warns against checking out PR code in pull_request_target workflows. 1
Vulnerable Instance
- Workflow triggers on
pull_request_target. - Step checks out
github.event.pull_request.head.sha. - Subsequent steps run build/test scripts from the fork.
name: PR Target
on:
pull_request_target:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }} # Dangerous
- run: npm testMitigation Strategies
- Use
pull_requestfor untrusted code
Standard PR workflows run with read-only tokens; use them for building fork contributions. - Never checkout head ref in
pull_request_target
If you need repository context, only check out the base branch (github.event.pull_request.base.ref). - Split validation and privileged actions
Usepull_requestto build/test andworkflow_dispatch/pushfor deployments. - Minimize permissions
Explicitly setpermissions: read-allinpull_request_targetworkflows; escalate only after manual review. - Validate inputs and artifacts
Treat data from the head repo as untrusted; avoid running scripts or commands from it.
Secure Version
name: PR Validation
on: pull_request
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm test
name: PR Target Labeler
on:
pull_request_target:
branches: [main]
jobs:
- build:
+ label:
runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ pull-requests: write
steps:
- uses: actions/checkout@v4
with:
- ref: ${{ github.event.pull_request.head.sha }} # Dangerous
- - run: npm test
+ ref: ${{ github.event.pull_request.base.ref }}
+ - run: gh pr edit ${{ github.event.pull_request.number }} --add-label "triaged"
Impact
| Dimension | Severity | Notes |
|---|---|---|
| Likelihood | Many tutorials misuse pull_request_target for testing forks. | |
| Risk | Attackers gain maintainer-level repo access and secrets. | |
| Blast radius | Entire repository, environments, and registries tied to the token are exposed. |
References
- GitHub Security Lab, “Untrusted input in GitHub Actions,” https://securitylab.github.com/research/github-actions-untrusted-input/ 1
- GitHub Docs, “Events that trigger workflows: pull_request_target,” https://docs.github.com/actions/using-workflows/events-that-trigger-workflows#pull_request_target
GitHub Security Lab, “Untrusted input in GitHub Actions,” https://securitylab.github.com/research/github-actions-untrusted-input/ ↩︎ ↩︎
Last updated on