Developer Tools

pull_request_target Is Off by Default on Public Repos From 2 November

GitHub blocks pull_request_target in public repos from 2 Nov 2026. What breaks, how to read evaluate-mode insights, and the migration patterns that work.

TechLogHub Editorial
September 22, 2026
7 min read
0 views

Share Article

Diagram of a fork pull request stopped at a policy gate before a workflow holding secrets, with a split-workflow path.

pull_request_target Is Off by Default on Public Repos From 2 November

Quick answer: On 2 November 2026 GitHub starts enforcing a default rule that blocks the pull_request_target event in public repositories. Private and internal repos are not affected. The rule is running in evaluate mode right now, so you can see exactly which runs it would block. Move anything that doesn't need secrets to pull_request, split the rest into a build step and a privileged step, and only then allow the event back for the specific workflow that needs it.

GitHub is switching off the Actions trigger behind the whole "pwn request" class of bugs, for every public repository. From 2 November 2026, workflows that run on pull_request_target in a public repo will be blocked unless someone has explicitly allowed the event. That is a good call, and it will still break a lot of labelers, comment bots and preview-deploy pipelines that nobody has looked at in years.

What changed on 17 September, and what happens on 2 November

On 17 September GitHub announced that workflow execution protections are generally available. They are allowlists at enterprise, organisation and repository level. Actor rules decide who can trigger a run. Event rules decide which events can trigger one. GA added per-workflow-file targeting, an insights view and a REST API.

The same announcement added a default rule that disables pull_request_target in public repositories. It starts in evaluate mode, which logs the runs it would block without blocking anything. GitHub's pull_request_target security guide says the rule becomes enforced on 2 November for repositories that were still on the default policy before GA. Private and internal repositories are out of scope.

The first step came earlier. actions/checkout v7 shipped on 18 June and refuses to fetch fork pull-request code inside pull_request_target workflows, and inside workflow_run workflows triggered by a pull-request event. That behaviour was backported on 20 July to every supported major except v1. If you use a floating tag like @v4 you already have it. If you pinned a SHA, you don't.

LayerDateWhat it blocksOverride
actions/checkout v7 + backports18 Jun / 20 Jul 2026Checking out fork PR code in pull_request_target and PR-triggered workflow_runallow-unsafe-pr-checkout: true
Default event rule (evaluate)17 Sep 2026Nothing yet — logs would-be blocksn/a
Default event rule (enforced)2 Nov 2026The whole pull_request_target run, public repos onlyAllow the event in Actions policies

Why GitHub is doing this

The trigger is not a bug. It works exactly as documented, and that is the problem. A pull_request_target run gets the base repository's GITHUB_TOKEN and access to repository and organisation secrets. The workflow file comes from the default branch, so people assume it is safe. GitHub's guide is blunt about where it goes wrong: the vulnerability is completed by the next step, the one that runs code checked out from the pull request.

An attacker doesn't need to touch your workflow. They open a PR from a fork whose Makefile, test script, package.json lifecycle hook or config file runs a command. Your trusted workflow checks it out and runs npm test, and their code runs with your secrets. The whole attack is one pull request.

The checkout change closed the most common way in. The event rule closes the rest: a raw git fetch, a gh pr checkout, a tarball download.

What breaks on 2 November

Anything in a public repo that relies on pull_request_target and hasn't been explicitly allowed. In practice that means:

  • Labelers. The official actions/labeler README tells you to use on: pull_request_target. Every repo that copied it verbatim is on the list.
  • Comment bots. Coverage summaries, bundle-size reports, "thanks for your first PR" greetings, and AI review bots that post on fork PRs. They need a write token, which is why they were on this trigger.
  • Preview deploys. Workflows that build a fork's branch and push it to a hosting provider with a deploy token. These are the dangerous ones, and they should break.

A blocked run fails with a message naming the event and the workflow file, in the form Event 'pull_request_target' is not allowed to trigger Actions workflows. A maintainer who sees that cold on 3 November will allow the event repo-wide just to make it go away.

How to audit it this week

Evaluate mode is the point of the rollout. You have six weeks of real data on which runs would be blocked. Use it.

1. Find every workflow on the trigger

A code search for pull_request_target in path:.github/workflows across your organisation gives you the list. Include reusable workflows you maintain, since those get called from other people's repos. A text diff checker against the upstream example each one was copied from shows where someone later added a checkout step.

2. Read the policy insights

Under Settings → Actions → Policies at repository or organisation level, the insights view shows the runs the default rule would have stopped. It only lists workflows that actually fired, so it beats your grep.

3. Sort each workflow into one of three buckets

What the workflow doesRight trigger
Builds or tests PR code, needs no secretspull_request
Needs secrets or a write token, but never runs PR codeKeep pull_request_target, allow it for that one file
Needs to build PR code and use a secret with the resultSplit: pull_request builds, workflow_run publishes

The migration patterns that work

Most workflows: just use pull_request

GitHub's own advice is short: if you don't need secret access, use pull_request. It runs against the merge commit with a read-only token on fork PRs. A common reason CI ends up on pull_request_target is to make a status comment work. Losing the comment is cheaper than keeping the exposure. Write the result to the job summary instead.

The split pattern for comments and deploys

The unprivileged job runs on pull_request, builds the fork's code, and uploads its output (a coverage file, a size report, a static build) as an artifact. A second workflow on workflow_run downloads that artifact and does the privileged part. The privileged workflow never checks out or executes PR code, so the checkout v7 guard has nothing to refuse.

The catch is that the artifact is untrusted input. Parse it, validate it and never execute it. If it's JSON, check it against a schema. Generating a type from a known-good sample with a JSON-to-Zod converter takes a minute and turns "trust the fork's file" into "reject anything unexpected".

Allow the event narrowly, not globally

For workflows that really need the trigger and never touch PR code, like a labeler reading only the diff's file list, add an event rule that allows pull_request_target for that workflow file only. File-level targeting is new at GA and is the reason to wait for it instead of flipping the whole repo. Set permissions: to the minimum it needs, typically contents: read plus pull-requests: write and nothing else. Across many repos, manage the rules through the REST API so the allowlist is reviewed like code.

Don't reach for the escape hatches

allow-unsafe-pr-checkout: true exists, and the checkout team says it was deliberately named to stand out in code review. Treat any PR that adds it as a security review, not a CI fix. The same goes for an organisation-wide rule re-enabling the event.

Also, pinning actions/checkout to an old SHA to avoid the new guard is the wrong lesson from supply-chain advice. Pin to the v7 SHA. If you're comparing CI hardening tools while you're at it, the cloud and DevOps directory and the open-source listings are a good place to look for workflow linters that catch this pattern before it merges. We walked through a related credential cleanup in publishing to npm without long-lived tokens. Removing a secret beats guarding it.

FAQ

Does the 2 November rule affect private repositories?

No. GitHub's changelog says the default rule applies to public repositories only. Private and internal repositories are not covered by it, though an organisation can still add its own event rule for them.

Is pull_request_target being removed from GitHub Actions?

No. The event still exists and can be allowed through Actions event policies. What changes is the default for public repos: from 2 November it is blocked unless someone explicitly allows it.

How do I see which workflows will be blocked?

Open Settings, then Actions, then Policies at repository or organisation level and check the policy insights. While the default rule is in evaluate mode, insights lists the runs it would have blocked without stopping them.

Does actions/checkout still work in pull_request_target workflows?

Yes, for the base repository's code. Since the July 2026 backport, every supported major except v1 refuses to check out fork pull-request code in pull_request_target and PR-triggered workflow_run runs unless allow-unsafe-pr-checkout is set to true.

What should replace pull_request_target for PR comment bots?

Split the workflow. A pull_request job builds the fork's code and uploads the result as an artifact, then a workflow_run job downloads it and posts the comment with a write token. Treat the artifact as untrusted data and never execute it.


The trigger was always doing what the docs said. From 2 November, "we didn't read the docs" stops being a working security model for public repos.

Stay Updated

Get the next deep dive in your inbox

Subscribe for product analysis, engineering explainers, and practical guides published on TechLogHub.

See what launched this week

One email a week: new and trending developer tools, fresh comparisons, and what shipped. Unsubscribe in one click.