FR
live

GitHub Actions Blocks pull_request_target by Default in Public Repos on December 2

On November 2, 2026, GitHub announced that the pull_request_target event will be blocked by default in all public repositories from December 2, after brownouts on November 9 and 16. Teams that depend on this trigger to reach base-repo secrets must explicitly allow it through an Actions event policy before the deadline.

A row of identical access turnstiles in an empty corridor, one turnstile arm lifted with its amber indicator lit.

November 2, 2026. GitHub announces that the pull_request_target event will be blocked by default in all public repositories starting December 2, 2026. November 9, 2026. First brownout, from 16:00 to 18:00 UTC, when the rule is actually enforced as a test. November 16, 2026. Second brownout, same window. The mechanics are simple: one of the most dangerous triggers in GitHub Actions stops being available by default, and anyone who still needs it will have to say so explicitly.

For a team running CI on public repositories, this is not a footnote. It is the closing of a years-old trap — and a deadline you cannot afford to miss.

Why pull_request_target is a trap

The defining trait of pull_request_target fits one sentence: the workflow runs in the context of the base repository, with access to its secrets. Unlike pull_request — which runs in the fork’s context, without secrets — pull_request_target was built for cases where automation needs privileges (commenting, labeling, deploying a preview) on a pull request from a fork.

The problem has been known for a long time. If a pull_request_target workflow checks out and runs untrusted code from the PR’s branch — a checkout of the head SHA, then npm install && npm test, for instance — then any fork contributor can steal secrets or compromise the pipeline. The dangerous pattern looks like this:

yaml
on:
  pull_request_target

jobs:
  preview:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.event.pull_request.head.sha }}
      - run: npm ci && npm test

Here, the ref: …head.sha line ticks exactly the disaster box: the runner, launched with the base repository’s privileges, executes code controlled by a third party. It is a classic entry point for exfiltrating GITHUB_TOKEN, npm keys, or deployment secrets.

Examples are not hard to find: campaigns of fork PRs targeting pull_request_target workflows to exfiltrate npm, PyPI, or deployment tokens have been documented for years by open-source security teams. The pattern is always the same: an anonymous fork, an innocuous pull request, an over-trusting workflow.

The three triggers, and when to use them

Choosing the right trigger is not a cosmetic detail: it decides which code runs with which privileges.

TriggerExecution contextBase-repo secretsLegitimate use
pull_requestFork (isolated)NoBuilding and testing PR code
pull_request_targetBase repositoryYesCommenting, labeling, previewing
workflow_runBase repository, after a workflowYesProcessing artifacts from a trusted build

The reading rule fits one sentence: the more privileged the context, the more trusted the code running in it must be. pull_request is the right choice for anything that executes untrusted code — there, a malicious contributor cannot reach the secrets. pull_request_target and workflow_run are reserved for trusted actions that never consume the PR’s content as code.

That is exactly the discipline GitHub’s new rule enforces by default: it does not remove the possibility, it reverses the burden of proof — you must declare that you need the privileged context.

What the rule changes, and its schedule

The rule is introduced through workflow execution protections, and it works in two phases.

Evaluate mode, now. Until the enforcement date, the rule runs in evaluate mode: it blocks nothing but flags the runs it would block. This is your window to measure the impact without suffering a break.

The brownouts, November 9 and 16. During those two slots — 16:00 to 18:00 UTC — the protection is actually enforced. Blocked pull_request_target attempts produce failed runs with an error annotation, and the workflow will not run. After each slot, the rule returns to evaluate mode. These windows are your free dress rehearsal: they show you exactly which workflows would break on December 2.

Permanent enforcement, December 2. From that date the rule is permanent. The scope is precise: public repositories on GitHub Free, Team, and Enterprise Cloud. Private and internal repositories are unaffected, as is GitHub Enterprise Server.

The postponement from November 2 to December 2 grants an extra month of runway — but the principle is unchanged: the default becomes “block”.

What to do before December 2

Two options are available, and the right choice depends on why you were using pull_request_target.

  • Keep the default rule. If your workflows can live without it, do nothing — that is the safest posture. Migrate cases that need no secrets to pull_request (building and testing untrusted code), and reserve privileged actions (labeling, commenting) for a bot or a dedicated workflow triggered some other way.
  • Explicitly allow the trigger. If a legitimate workflow truly depends on pull_request_target, open the Actions event policies and allow it, ideally by targeting specific workflow files rather than opening the door for the whole repository.

To prepare, use Insights to see which runs the rule would block today. The two brownouts then do the verification for you: watch them, and every annotated failed run tells you exactly what to fix.

The broader recommendation is this: even where pull_request_target stays allowed, never run untrusted fork code in its context. The trigger is not the enemy; running third-party code with secrets is.

Verdict

This rule closes a design hole that has cost the open-source ecosystem dearly — secrets exfiltrated through fake fork PRs, again and again. The schedule is reasonable: a month, two dress rehearsals, and a clear scope that spares private repositories.

If your public repository uses pull_request_target to test PR code, the right answer is not to re-allow it — it is to migrate to pull_request and move privileged actions out of the untrusted-code path. If you depend on it for trusted work (labels, comments, previews), allow it explicitly by targeting the affected workflows, not the whole repository. Either way, do not skip the November 9 and 16 brownouts: they are the only free tests you get before the rule becomes permanent.

References

The cyber brief, every Tuesday

The flaws that matter and the patches to apply, in a ten-minute read.

No spam. One-click unsubscribe.
read next

On the same topic

Kubernetes Gateway API 1.7 promotes HTTPRoute retries to the Standard channel

On October 29, 2026, Kubernetes Gateway API shipped version 1.7.0: HTTPRoute retry configuration graduated to the Standard channel while distributed tracing, pre-routing filters, and session persistence landed as experimental. Teams exposing traffic across multiple gateway implementations should revisit their retry annotations and telemetry policy before upgrading.

← Back to the feed

Type at least two characters.

↑ ↓ navigate ↵ open esc dismiss