# GitHub’s New Actions Default Puts Privileged Pull Request Workflows on Notice

- Link: https://thestackobserver.com/githubs-new-actions-default-puts-privileged-pull-request-workflows-on-notice/
- Published: 2026-11-09T11:12:17-05:00
- Author: Stackxx

GitHub is about to make a risky GitHub Actions trigger opt-in for public repositories.
Beginning December 2, 2026, workflows triggered by `pull_request_target` will be
blocked by default unless an applicable Actions event policy explicitly allows them.
The first scheduled brownout is today, November 9, from 16:00 to 18:00 UTC, followed
by a second on November 16.

For platform teams, this is more than a compatibility notice. It is a deadline to
identify where privileged automation meets code supplied by strangers. The right
response is not a blanket allow rule that restores yesterday’s behavior. Teams should
use the enforcement change to separate untrusted pull-request computation from privileged
repository operations, and grant exceptions only to workflows whose design makes
that boundary explicit.

## Why this trigger receives special treatment

The ordinary `pull_request` trigger is designed for testing proposed changes. When
a pull request comes from a fork, GitHub limits the workflow token and withholds
repository secrets. That makes it a sensible place to compile code, run tests, lint
files, or generate test results supplied by an external contributor.

`pull_request_target` solves a different problem. It runs in the context of the 
base repository rather than the pull request’s merge commit. The workflow definition
comes from the trusted base branch and can receive permissions or secrets needed
to label a pull request, leave a comment, or perform another repository-side action.

That privilege becomes dangerous when the workflow also checks out the contributor’s
head commit and executes it. A malicious contributor can change build scripts, tests,
package manifests, installer hooks, or other files that the job evaluates. If those
files run in a job with a write-capable token or secrets, the contributor may gain
a path to repository compromise or credential theft.

The subtlety is that a workflow can look safe because its YAML lives on the base
branch. The weak point is often what happens after checkout: `npm install`, a Make
target, a test runner, a documentation generator, or even a third-party action may
interpret attacker-controlled content. The trust boundary follows the data and executable
content, not merely the location of the workflow file.

## What changes on December 2

GitHub’s default workflow execution protection applies to public repositories on
GitHub Free, GitHub Team, and GitHub Enterprise Cloud. Private and internal repositories
are not affected, and neither is GitHub Enterprise Server. Before permanent enforcement,
GitHub is placing the rule in evaluate mode so organizations can see which runs 
would be blocked.

During the November 9 and November 16 brownouts, affected workflow attempts will
fail with an error annotation rather than execute. After each two-hour window, the
rule returns to evaluate mode until permanent enforcement begins. Those failures
are useful production evidence: they reveal active paths that an inventory based
only on repository search might miss.

Platform owners have two formal choices. They can keep the default rule and let 
it block the event, or explicitly allow `pull_request_target` through an applicable
Actions event policy. GitHub supports targeting specific workflow files, which is
materially safer than applying a broad organization-wide exception. But an allow
rule answers only whether a workflow may start; it does not prove that the workflow
handles untrusted input safely.

## Build an inventory from execution data

Start with GitHub Insights and the evaluation results for the new protection. Record
the repository, workflow path, owner, recent run count, requested permissions, secrets
or environments used, and whether fork-originated pull requests are expected. Add
the brownout failures to the same inventory.

Then search the organization’s public repositories for `pull_request_target`. Static
search catches dormant workflows that evaluation mode may not observe before December
2. It also finds reusable or copied workflow patterns whose risk is shared even 
if only one repository currently receives external contributions.

For each match, trace more than the trigger declaration. Review the entire job graph
and answer these questions:

 * Does any step check out the pull request head SHA, head branch, or fork repository?
 * Does the job run scripts, tests, build tools, package installation, templates,
   or configuration taken from the pull request?
 * Can pull-request fields such as titles, branch names, or comments reach a shell
   command or expression without safe handling?
 * What are the effective `GITHUB_TOKEN` permissions at workflow and job level?
 * Which repository, organization, or environment secrets can the job access?
 * Can a third-party action consume pull-request-controlled files while credentials
   remain available?

Classify each workflow as retire, replace, redesign, or explicitly allow. A workflow
that no longer serves a user should be retired. One that only needs read-only testing
should use `pull_request`. One that mixes testing with a privileged follow-up should
be split. Only narrow base-context automation that does not execute untrusted code
should move toward an exception.

## Prefer a two-stage workflow for mixed-trust jobs

A common requirement is to test a forked contribution and then report a result back
to the pull request. The secure pattern divides that work into two stages.

### Stage one: compute without privilege

Use `pull_request` to check out and execute the proposed code. Set explicit read-
only token permissions, avoid secrets, and treat the runner as disposable. Produce
only the minimum result needed by the next stage, such as a test status, coverage
summary, or pull-request number. Upload that result as an artifact.

This is still untrusted execution. It needs normal runner isolation, dependency 
controls, timeouts, and cost-abuse safeguards. The important distinction is that
compromise of this stage should not provide a write token or sensitive credential.

### Stage two: apply a narrowly scoped result

Use a privileged workflow, commonly triggered by `workflow_run`, to retrieve the
result and perform the repository-side action. Grant only the permission needed,
such as `pull-requests: write` for a comment. Do not execute binaries, scripts, 
archives, or commands supplied by the artifact.

The artifact crosses a trust boundary, so it remains attacker-controlled data. Validate
its format, size, and allowed values. A numeric pull-request identifier or bounded
text summary can be handled safely; a compiled utility or shell fragment from the
first stage cannot. Extract artifacts outside a workspace containing executable 
hooks, and never assume that “produced by CI” means trusted.

This architecture introduces a second workflow and some coordination overhead, but
it gives reviewers a clear security invariant: untrusted code runs without privilege,
while privileged code consumes a small, validated data contract.

## When an explicit allow is reasonable

Some `pull_request_target` workflows are aligned with the trigger’s intended use.
A job may label a pull request according to trusted metadata, welcome a first-time
contributor, or post a standard comment without checking out or evaluating the proposed
code. Those workflows may warrant targeted exceptions.

Before allowing one, make its permissions explicit. GitHub’s defaults and organization
settings can evolve, while a job-level declaration is reviewable beside the automation.
Remove unnecessary checkout steps, avoid secrets when the repository token is sufficient,
pin third-party actions to immutable commit SHAs, and constrain the workflow to 
the activity types it actually handles.

Workflow-file targeting should be the exception mechanism of choice. Avoid allowing
the event across every workflow in an organization or repository merely to clear
brownout failures. A broad rule expands the blast radius of future workflow additions
and makes a security-sensitive trigger feel routine.

Manual labels are not a durable substitute for separation. Requiring a maintainer
to add a “safe to test” label can reduce immediate exposure, but contributors may
push new commits after review, creating a race between approval and execution. Use
such a gate only as a temporary containment step while redesigning the workflow.

## Make the migration observable

Treat the two brownouts as controlled resilience tests. Assign an owner to watch
blocked-run annotations, developer reports, and repository automation during each
window. Compare observed failures with the inventory and record workflows that were
overlooked. A failure in a low-traffic public repository is still relevant if that
project accepts forked contributions.

Track completion with a small set of operational measures: total public repositories
scanned, active `pull_request_target` workflows, workflows removed or converted,
workflows split into unprivileged and privileged stages, and targeted exceptions
approved. Every exception should carry an owner, rationale, review date, and the
precise workflow path covered by policy.

After remediation, test both trusted and fork-based pull requests. Confirm that 
required checks still report correctly, comments or labels appear only when expected,
secrets are absent from untrusted jobs, and token permissions match the design. 
Review open pull requests created before a vulnerable workflow was fixed, because
their behavior can retain older workflow assumptions; closing or rebasing them may
be necessary.

## A practical deadline plan

 * **Immediately:** export evaluation findings, search all public repositories, 
   and identify owners for every active workflow.
 * **During the November 9 brownout:** capture actual blocked runs and validate 
   that critical maintainer automation has a remediation path.
 * **Before November 16:** convert straightforward test jobs to `pull_request`, 
   remove obsolete workflows, and prototype two-stage designs.
 * **During the November 16 brownout:** verify remediations under enforcement and
   investigate every unexpected failure.
 * **Before December 2:** approve only workflow-targeted exceptions, document their
   threat model, and test fork contributions end to end.
 * **After enforcement:** review exceptions periodically and add policy checks so
   new privileged triggers cannot appear without ownership.

## The platform lesson behind the new default

GitHub is changing the safe default because repository automation now carries production-
grade authority. A pull request is not just source code awaiting review; it can 
be input to a distributed execution system with tokens, secrets, package credentials,
cloud identities, and write access.

The durable control is a visible trust boundary. External contributions should execute
in an environment where compromise is expected and privileges are minimal. Repository
mutations should occur in a separate context with narrow permissions and a validated
input contract. GitHub’s December 2 enforcement creates urgency, but teams that 
adopt that design will be better protected against the next dangerous trigger, action,
or automation shortcut as well.

## Sources

 * [GitHub Changelog: pull_request_target blocked by default December 2](https://github.blog/changelog/2026-11-02-pull_request_target-blocked-by-default-december-2/)
 * [GitHub Security Lab: Preventing pwn requests](https://securitylab.github.com/resources/github-actions-preventing-pwn-requests/)
 * [GitHub Docs: Events that trigger workflows](https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows#pull_request_target)
