
GitHub shipped actions/checkout v7 on June 18 with one critical change: by default, it refuses to check out fork pull request code when your workflow runs under pull_request_target or workflow_run. This closes the most common door for “pwn request” attacks — a CI supply chain exploit class that breached 23,000+ repositories in the 2025 tj-actions incident. On July 16, GitHub backports this protection to all currently supported major versions. If your workflow uses a floating tag like actions/checkout@v4, that date could quietly break your CI.
What a Pwn Request Actually Is
The term comes from GitHub Security Lab. The attack exploits how pull_request_target works: it runs in the context of the base repository, with full access to the base repo’s GITHUB_TOKEN, secrets, and cache. That’s by design — the trigger exists so workflows can post comments or status checks on fork PRs, which requires write access to the base.
The danger arrives when the same workflow also checks out the fork’s head commit to run tests or a build. Now the fork author’s code — from an external contributor you may never have reviewed — is executing with your repository’s full privileges. They can read secrets, exfiltrate API tokens, push to npm, or silently modify what your release pipeline publishes.
This is exactly what happened to the TanStack ecosystem earlier this year: 170 npm packages were compromised through a pwn request exploit in CI. The 2025 tj-actions/changed-files incident used a different vector but the same privilege model — and it hit over 23,000 repositories before it was caught.
What Checkout v7 Blocks
The dangerous pattern looks like this:
on:
pull_request_target:
types: [opened, synchronize]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }} # fork code runs here
Starting with v7, that checkout step fails by default. GitHub’s reasoning is blunt: if you need to run the fork’s code in a privileged context, you should have to say so explicitly.
The only way to restore the old behavior is to set a new flag with a deliberately ugly name:
- uses: actions/checkout@v7
with:
ref: ${{ github.event.pull_request.head.sha }}
allow-unsafe-pr-checkout: true # you have to say it out loud
The flag name is not an accident. It’s designed to be embarrassing to merge and easy to catch in automated scanning. That’s the right call.
Three Ways to Migrate
Path 1 — Upgrade and do nothing else. If your pull_request_target workflow doesn’t actually need the fork’s source code — it just posts a comment or runs a check against the base branch — upgrading to actions/checkout@v7 is all you need. Most workflows in this category are fine without touching anything else.
Path 2 — Switch to pull_request. If your workflow runs tests against the fork’s changes but doesn’t need write-back access or secrets, just switch the trigger. The pull_request event runs in the fork’s context with no access to base-repo secrets. It’s the cleanest fix for the majority of open-source CI workflows.
Path 3 — Two-workflow split. For cases where you genuinely need both: test the fork’s code AND post results back to the PR with secrets. Workflow A triggers on pull_request, runs tests, uploads artifacts — no secrets involved. Workflow B triggers on workflow_run after Workflow A completes, downloads the artifacts, posts status — no fork code checkout. More setup, zero privilege escalation risk.
What v7 Does Not Cover
v7 is a guardrail, not a complete fix. If your workflow uses git fetch origin pull/${{ github.event.pull_request.number }}/head or gh pr checkout in a run: step, none of that is blocked. The protection applies only to the actions/checkout action itself. Similarly, the issue_comment trigger — another common pwn request vector — is out of scope.
GitHub’s 2026 security roadmap addresses the broader picture: workflow dependency locking (think go.sum but for action SHAs), scoped secrets that limit credential exposure per job, and an immutable action audit log. Those features are in preview. The checkout change is what’s shipping now.
What You Need to Do Before July 16
Search your workflow files for pull_request_target and workflow_run triggers. If any of them also run actions/checkout with a fork PR ref, you have three weeks to choose a migration path. Workflows pinned to floating major tags inherit the change automatically on July 16 — your CI might break that morning without warning. Workflows pinned to specific SHAs or minor versions are insulated from the auto-backport but should still be upgraded.
GitLab and CircleCI have kept fork builds isolated from secrets by default since their early days. GitHub is late to this, but the implementation is clean — and making the opt-out explicit is exactly the right approach. See the full GitHub Changelog entry for complete migration details. If your pipeline breaks on July 16, it means you had an open supply chain hole. Better to find out now.













