News

GitHub Actions Execution Protections Are GA: Audit pull_request_target Before November 2

GitHub's new secure default will block pull_request_target in affected public repositories on November 2, 2026. Inventory each workflow now, inspect evaluate-mode evidence, and prove whether to remove, replace, or narrowly allow the trigger.

September 18, 2026

A glass-walled miniature corridor crossed by glowing teal and orange light paths on a dark platform.
The bounded corridor represents a narrowly scoped event policy that limits which workflow path can cross into privileged execution.

First Prove That the Default Applies

GitHub announced general availability for workflow execution protections on September 17, 2026. These policies allowlist actors and events before a workflow runs. The release also adds workflow-file targeting, policy Insights, and REST API management, while retaining evaluate mode for observing what enforcement would block.

The November change is narrower than “all pull_request_target stops.” GitHub says the new default disables that event in public repositories that do not already have an applicable event policy. It does not apply to private or internal repositories. Automatic enforcement on November 2 applies to affected repositories that were using GitHub's default pull_request_target policy before general availability.

Record the effective policy scope before editing YAML: enterprise, organization, or repository; policy name; owner; current mode; and whether another event policy already applies. Actions policies live in the Policies section of Actions settings, separate from General settings. A repository administrator may see the workflow file but not own the higher-level rule that determines whether it can run.

Do not treat evaluate mode as a safety verdict

An evaluate result tells you which run would be blocked. It does not inspect the workflow's checkout ref, commands, token permissions, or secret use. Keep impact evidence and trust-boundary review as separate columns.

Build an Inventory From Files and Runs

Search every default branch for the exact event and include reusable or generated workflow paths in your review. A simple first pass is:

git grep -n -E '^\s*pull_request_target:' -- '**/.github/workflows/*.yml' '**/.github/workflows/*.yaml'

Do not stop at a zero-result search: YAML may use an inline event list, unusual indentation, or generated files. Follow with a structured YAML scan or manual review of each on block. Then open Actions policy Insights and export or capture evaluate-mode results for the same period. Join the two sets by repository and workflow path. The file inventory finds dormant workflows; Insights finds observed runs and shows practical enforcement impact.

For each match, write one row with workflow path, jobs, event activity used, token permissions, secrets or environments referenced, checked-out repository and ref, scripts executed, artifacts written, and the evaluate result. This is the same provenance discipline used in our reusable-workflow identity fixture: a green check becomes meaningful when you can identify what implementation and policy produced it.

FieldEvidence to retainFailure signal
TriggerWorkflow path and exact on configurationInventory relies on recent runs but omits dormant files
Trust boundaryCheckout ref, commands, permissions, secrets, environmentsFork-controlled code reaches a privileged step
PolicyScope, owner, mode, matching event ruleRepository setting is assumed to be effective policy
ImpactDated Insights result or failed-run evidenceNo evidence for a workflow that is still required
DecisionRemove, replace, or explicitly allow, with reviewerBlanket allow restores every matching workflow

Review the Base-Repository Boundary

pull_request_target is useful because it runs in the base-repository context. That same property is why GitHub warns about workflows that execute code from a fork: the untrusted code can poison the pipeline and expose secrets available to the workflow. The event alone is not proof of exploitation. The dangerous path is the connection between fork-controlled input and a privileged command, token, secret, artifact, cache, or deployment.

Trace data instead of limiting the scan to actions/checkout. Check which repository and ref are checked out; whether a pull-request head SHA enters a shell command; whether an action, script, package manifest, configuration file, or test from the fork is executed; and whether later jobs download artifacts created in a lower-trust context. Review explicit and inherited permissions. If caching is involved, apply the trigger-by-trigger method from our Actions cache poisoning fixture.

Use a harmless sentinel for the test. For example, place a unique marker in the fork and make the privileged workflow fail if that marker is executed or loaded. Do not put a production secret in the fixture to see whether it leaks. A controlled failure proves the boundary without creating the incident the test is meant to prevent.

Classify Every Trigger: Remove, Replace, or Allow

Remove the event when the workflow is obsolete, duplicated, or no longer produces a required result. Delete the trigger and confirm that no branch rule, required check, bot, or release process still waits for its check name.

Replace it when the job can operate in the pull request's lower-trust context. Move validation to pull_request, reduce permissions, and split any privileged follow-up into a separate workflow with an explicit artifact and approval contract. Preserve check names deliberately if branch protection depends on them, and test both a same-repository pull request and a fork pull request.

Explicitly allow when the base-context capability is necessary and the trust-boundary review shows that fork-controlled code cannot reach privileged execution. GitHub allows an applicable event policy to permit pull_request_target, and the GA feature can scope that decision to specific workflow files. Prefer that narrow path over a repository-wide exception. Name the policy owner, permitted workflow path, reason, review date, and the change that would invalidate the decision.

This classification is deliberately stricter than “block or allow.” Replacement keeps a required check while removing the reason it needed elevated context. It also forces reviewers to separate business purpose from historical implementation.

Run a Four-Case Migration Test

Use a disposable public repository or a non-production workflow that represents the same boundary. Freeze the workflow path and commit SHA, then run four cases:

  1. Evaluate baseline: trigger the current workflow from a fork pull request and retain the matching Insights result.
  2. Enforced negative: enforce the event rule and repeat the same request. GitHub's documentation says a disallowed run fails with an error; record that error and verify no privileged job executed.
  3. Chosen positive: apply the replacement or workflow-file-specific allow rule, repeat the request, and confirm the intended workflow and jobs run while unrelated ones do not.
  4. Boundary probe: change the harmless fork sentinel and confirm it cannot enter a privileged command, secret-bearing step, trusted cache write, or deployment.

Keep the before and after fixtures identical except for the policy or trigger change being tested. Record repository, pull-request URL, head and base SHAs, workflow path, policy scope and revision, expected result, observed conclusion and timestamp. If the positive case needs a privileged follow-up, use an artifact with a declared schema and verify its producer identity before consumption.

workflow: .github/workflows/label-pr.yml
decision: explicitly_allow
policy_scope: organization
evaluate_result: would_block
negative_result: event_not_allowed
positive_result: label_job_only
fork_sentinel_executed: false
permissions: pull-requests:write, contents:read
owner: developer-platform
review_by: 2026-10-15
rollback: restore_blocking_event_rule

Finish With an Enforcement Record

Complete the audit when every inventory row has a decision and reproducible evidence. Resolve required-check dependencies before removing a workflow. For replacements, retain the lower-trust fork test and any privileged follow-up test. For allows, retain the workflow-targeted policy, owner, reason, review date, and boundary probe.

Schedule one review before November 2 and one after enforcement. The first catches workflows that would unexpectedly fail. The second confirms the effective policy and looks for broad exceptions added under deadline pressure. GitHub's Insights can show policy impact before and after enforcement, but your repository record must explain why each remaining run is needed and what prevents fork input from becoming privileged execution.

The goal is not to make the warning disappear. It is to reach November 2 with no ambiguous workflow: unused triggers removed, lower-trust jobs moved, exceptional base-context workflows narrowly allowed, and each decision backed by a test another maintainer can repeat.

Sources checked September 18, 2026