Skip to content

Back to the catalog

Securely using pull_request_target - GitHub Enterprise Cloud Docs
docs.github.comarticle

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.

TL;DR GitHub's official guide to avoiding "pwn request" attacks when using pull_request_target, including its new default-blocking policy and actions/checkout's allow-unsafe-pr-checkout safeguard.
Document

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 }}/merge
  • repository: ${{ 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

Techniques named here