pull_request vs pull_request_target for fork pull requests
Verdict: Use pull_request_target when a fork PR workflow needs write access and secrets; it runs in the base repository context and checks out the base ref. Never also check out the PR head under it, or untrusted code runs with secrets.
| Criterion | pull_request | pull_request_target |
|---|---|---|
| Runs in | The fork's own workflow and code | The base repository context and workflow definition |
| Token for fork PRs | Read-only GITHUB_TOKEN by default | Base-repository permissions with secrets access |
| Default checkout | The pull request head ref | The base branch ref, which is why it is safer |
| Main hazard | Limited: token is read-only for forks | Checking out the PR head executes untrusted code with secrets |
Rules
- pull_request_target runs with the base repository's permissions and secrets regardless of where the PR originated, while pull_request is read-only for fork PRs.
- GITHUB_TOKEN defaults to read-only for fork-originated pull_request runs; a repository setting can send write tokens to those runs when needed.
- Combining pull_request_target with an explicit checkout of the PR head ref lets attacker-controlled scripts run with secrets access and exfiltrate them.
- Harden GITHUB_TOKEN by defaulting it to read access for contents, then granting extra scopes only to the jobs that need them.
- For private or internal repos, require approval before outside-collaborator fork workflows run and keep their token read-only.
Traps
- pull_request_target does not check out the fork head by default; it uses the base ref, so adding a head checkout is what makes it dangerous.
- Token permissions are not identical between pull_request and pull_request_target; the latter carries base-repository secrets.