Introduction
pull_request_target is powerful because it runs in the security context of the base repository, not the fork. That is exactly why it becomes dangerous when a workflow checks out and executes code from the pull request head. A malicious contributor can turn that behavior into privileged code execution, secret exposure, or write access abuse unless the workflow is designed to keep trusted and untrusted code paths separate.
Symptoms
- GitHub warns that a
pull_request_targetworkflow may be vulnerable - The workflow checks out PR head code and then runs scripts with repository permissions
- Maintainers want to comment on or label fork PRs, but the workflow also executes contributor code
- Security review flags the workflow as unsafe even though it appears to work
Common Causes
pull_request_targetis used whenpull_requestwould have been sufficient- The workflow checks out
github.event.pull_request.head.shaand executes repository scripts - Secrets or write-scoped tokens are available in the same job that executes fork-controlled code
- The workflow mixes safe PR metadata actions with unsafe build or test steps
Step-by-Step Fix
- 1.**Use
pull_requestwhen you do not need privileged repository context** - 2.If the workflow only needs to test untrusted PR code, prefer the safer event.
on:
pull_request:- 1.**Keep
pull_request_targetjobs limited to trusted operations** - 2.Use it for labeling, commenting, or other base-repo controlled actions, not for executing fork code with elevated permissions.
- 3.Never execute PR head code in the same privileged job
- 4.If you must inspect PR code, do it in a separate low-privilege workflow path with no secrets or write tokens.
- 5.Review third-party actions and token permissions
- 6.Even a well-designed workflow becomes risky if it grants unnecessary write permissions or uses unpinned external actions carelessly.
Prevention
- Default to
pull_requestfor untrusted code execution - Use
pull_request_targetonly for narrowly scoped trusted automation - Separate privileged metadata actions from build and test execution
- Audit workflow permissions and checkout behavior whenever fork support changes