
Securely using pull_request_target - GitHub Enterprise Cloud Docs
GitHub's official guide on securely using the pull_request_target GitHub Actions trigger, explaining how it differs from pull_request by running workflow code and actions/checkout from the base repository's default branch while granting secrets and a privileged GITHUB_TOKEN. It details how "pwn request" vulnerabilities are introduced when workflows check out and execute a fork's pull request head (e.g. via ref: github.event.pull_request.head.sha), describes GitHub's new default policy that blocks pull_request_target in public repos (enforced starting Nov 2 2026), and lists hardening controls including least-privilege GITHUB_TOKEN, read-only cache access, isolated self-hosted runners, and the explicit allow-unsafe-pr-checkout opt-out flag in actions/checkout.
What it is
GitHub's reference on the pull_request_target Actions trigger. The existing summary covers the pwn-request mechanism, the Nov 2 2026 default-policy block, and the hardening list. What it omits are the scope boundaries of that policy, the additional vulnerable event types, and a critical limit on the allow-unsafe-pr-checkout opt-out — all of which change what an engineer actually needs to check.
Preconditions / Affected
The default policy that blocks pull_request_target does not apply to private or internal repositories — only public ones. It also does not replace an event policy you have already configured. Right now it runs in evaluate mode: runs continue unchanged, and you use policy insights to see which runs would be blocked. Enforcement on November 2, 2026 hits only repos that were on the default policy before general availability.
What to do
Before enforcement, use policy insights to list workflows using pull_request_target, then for each one decide:
- Doesn't need it → switch to
pull_request(same triggers, safe fork handling). - Must keep it → create/update an Actions event policy that explicitly allows
pull_request_target. - Don't want it → leave the default policy; it will be blocked after enforcement.
The opt-out has a sharp limit the summary doesn't state: allow-unsafe-pr-checkout: true only covers fork pull-request refs. It does not cover checking out an unrelated third-party repo, fetching via git fetch or gh pr checkout, or running a downloaded artifact — those remain unguarded.
Also enable CodeQL for GitHub Actions (default setup for code scanning) to catch pwn-request and command-injection shapes statically.
Other vulnerable shapes and events
The pwn pattern is not unique to pull_request_target. Any secret-bearing event that checks out and executes untrusted code is vulnerable — notably issue_comment and workflow_run. A workflow_run workflow must treat artifacts uploaded by other workflows as untrusted data, since their contents can originate from a fork.
Beyond ref: head.sha, the page names further insecure shapes to grep for:
ref: refs/pull/${{ github.event.pull_request.number }}/mergerepository: ${{ github.event.pull_request.head.repo.full_name }}- Fetching PR code outside
actions/checkout(git fetch,gh pr checkout, artifact download) and then running it.
Caveats
Cache access is read-only for pull_request_target, but a job can opt out by declaring a write-capable cache-mode — which reintroduces the cache-poisoning risk the restriction exists to prevent.
Technologies named here
- GitHub Actions
- actions/checkout
- GITHUB_TOKEN
- CodeQL for GitHub Actions
- GitHub Actions policy insights
- REST API endpoints for GitHub Actions policies
- CodeQL
Techniques named here
- Pwn Request
- Checking out PR head/merge commit and executing it
- Setting repository to the fork
- Fetching PR code outside actions/checkout
- Cache poisoning
- Command injection
Related in DevSecOps
JFrog: The Governance Gap Between Your Policy and Your Pipeline

Dev Machine Guard Now Supports Windows - StepSecurity

Socket: TanStack npm Packages Compromised
