Wiz: GitHub's 2026 pull_request_target protections leave residual Pwn request paths in GitHub Actions
Wiz research updates the GitHub Actions threat model for 2026. GitHub's platform changes (checkout protections in actions/checkout, read-only cache tokens and default event policies) make the default pull_request_target "Pwn request" harder to exploit, but they shift the vulnerability class rather than eliminate it. From December 2, pull_request_target will be blocked by default in public repositories without an explicit event policy. The default does not cover private or internal repositories or workflow_run. Attackers now need explicit opt-ins, outdated checkout versions, unprotected triggers or script injection. The post is a research analysis with an audit checklist, not a report of in-the-wild exploitation.
Entenda a falha
A vulnerabilidade
No CVE. Wiz describes a class of 'Pwn request' weaknesses in GitHub Actions workflows that still exist after GitHub's 2026 protections. The weaknesses are in workflows that run on pull_request_target, workflow_run, issue_comment and repository_dispatch, and they put repository secrets and the job token at risk. The attacker needs only to open a pull request, post a comment or influence a dispatch payload, and the workflow must be misconfigured. Examples are an explicit opt-in, an outdated actions/checkout, an unprotected trigger or script injection. The result is code execution with the job's secrets. Protected checkout versions are v2.8.0, v3.7.0, v4.4.0, v5.1.0, v6.1.0 and v7.0.0 or later. Workflows pinned by SHA to older releases such as v4.3.0 get no protection.
Como funciona
A workflow on a privileged trigger such as pull_request_target runs in the base repository's context with secrets, even when the event comes from a fork. If the workflow then fetches fork code, for example by checking out a PR ref, that untrusted code runs with those privileges. GitHub's checkout protections inside actions/checkout now block this by default for pull_request_target and workflow_run. Other paths remain. git clone, gh pr checkout or third-party actions fetch fork code without the checks. In issue_comment bot commands, refs/pull/N/merge can change after a maintainer comments. Interpolating ${{ }} values such as the PR title into a run step lets that text become part of the shell script. A privileged workflow_run can also download and execute artifacts uploaded by an unprivileged pull_request run.
Por que é vulnerável
The root cause is that untrusted input, whether fork code, comment or payload data, or artifacts, is handled inside a privileged context without a trust check. The 2026 fixes live inside actions/checkout and cover only pull_request_target and workflow_run, so any other way of fetching code or any other trigger is unprotected. The protections only exist in the backported releases, so a SHA pin to an older release runs legacy code with no checks. Script injection comes from GitHub substituting expression values into the script before the shell runs. Artifacts have no platform tainting. The 'Require approval for all external contributors' setting gates only pull_request, not pull_request_target. Wiz notes the default policy does not cover private or internal repositories or workflow_run.
Onde está
The articles point to the checkout protections in actions/checkout (backport release of July 20, 2026), the allow-unsafe-pr-checkout opt-in, and the workflow patterns on issue_comment, repository_dispatch, workflow_run and ${{ }} interpolation in run steps; no specific file or function is named.
Como foi descoberta
This is research by Wiz, published as an update to its GitHub Actions threat model after Part 1 (threat model and core defenses) and Part 2 (AI-powered actions). The company says it confirmed the SHA-pinning gap through empirical testing across workflow triggers. The post is an analysis with an audit checklist, not a report of in-the-wild exploitation. GitHub rolled out the protections in phases during 2026, and pull_request_target will be blocked by default in public repositories from December 2 unless an event policy allows it.
Explicação gerada por IA a partir da matéria e dos artigos, em 26/10/2026 11:17.
Detalhes técnicos
- SHA pinning paradox: the protections are backported into
actions/checkout(July 20, 2026 release). Workflows pinned to SHAs of older releases (e.g. v4.3.0) get no protection. Minimum patched versions are v2.8.0, v3.7.0, v4.4.0, v5.1.0, v6.1.0 and v7.0.0+. - Checkout bypasses: protections live inside the action, so
git clone,gh pr checkout,gh repo cloneand third-party checkout actions fetch fork code unrestricted. - Unprotected triggers: checkout protections cover only
pull_request_targetandworkflow_run.issue_commentbot commands (e.g./deploy) andrepository_dispatchremain exploitable even with checkout v7.refs/pull/N/mergeis mutable, which allows a time-of-check/time-of-use swap after a maintainer comments. - Script injection: interpolating
${{ github.event.pull_request.title }}intorun:steps gives code execution with job secrets and no checkout needed. - Artifact poisoning: an unprivileged
pull_requestworkflow uploads attacker-controlled artifacts, and a privilegedworkflow_rundownloads and executes them. There is no platform tainting for artifacts. - Self-hosted runners: on non-ephemeral runners, local package caches (
~/.npm,~/.cache/pip) and build directories persist between jobs and can poison later trusted release jobs. - Approval setting gap: "Require approval for all external contributors" gates only
pull_request, notpull_request_target. - Explicit opt-in:
allow-unsafe-pr-checkout: truere-enables untrusted fork checkouts.
Remediação
- Update SHA-pinned
actions/checkoutrefs to the patched releases. - Pass untrusted input through environment variables, never
${{ }}interpolation. - For
issue_commentandrepository_dispatch, verify the actor's real permission, check out the exact head SHA, and validate payloads against an allowlist. - Treat artifacts from less-trusted runs as untrusted data and never execute them.
- Use ephemeral runners and separate runner groups for untrusted and trusted workflows.
- Put privileged jobs behind environments with required reviewers or Workflow Execution Protections actor rules.
- Before December 2, review policy insights, move workflows to
pull_requestwhere possible, and allowlist only audited files in an explicit event policy. - Audit with zizmor, Wiz Code or the grep and SHA-resolution scripts provided in the article.
Linha do tempo
-
Wiz: GitHub's 2026 pull_request_target protections leave residual Pwn request paths in GitHub Actions
ler a análise desta fonte ocultar
Wiz research updates the GitHub Actions threat model for 2026. GitHub's platform changes (checkout protections in
actions/checkout, read-only cache tokens and default event policies) make the default pull_request_target "Pwn request" harder to exploit, but they shift the vulnerability class rather than eliminate it. From December 2,pull_request_targetwill be blocked by default in public repositories without an explicit event policy. The default does not cover private or internal repositories orworkflow_run. Attackers now need explicit opt-ins, outdated checkout versions, unprotected triggers or script injection. The post is a research analysis with an audit checklist, not a report of in-the-wild exploitation.Technical Details
- SHA pinning paradox: the protections are backported into
actions/checkout(July 20, 2026 release). Workflows pinned to SHAs of older releases (e.g. v4.3.0) get no protection. Minimum patched versions are v2.8.0, v3.7.0, v4.4.0, v5.1.0, v6.1.0 and v7.0.0+. - Checkout bypasses: protections live inside the action, so
git clone,gh pr checkout,gh repo cloneand third-party checkout actions fetch fork code unrestricted. - Unprotected triggers: checkout protections cover only
pull_request_targetandworkflow_run.issue_commentbot commands (e.g./deploy) andrepository_dispatchremain exploitable even with checkout v7.refs/pull/N/mergeis mutable, which allows a time-of-check/time-of-use swap after a maintainer comments. - Script injection: interpolating
${{ github.event.pull_request.title }}intorun:steps gives code execution with job secrets and no checkout needed. - Artifact poisoning: an unprivileged
pull_requestworkflow uploads attacker-controlled artifacts, and a privilegedworkflow_rundownloads and executes them. There is no platform tainting for artifacts. - Self-hosted runners: on non-ephemeral runners, local package caches (
~/.npm,~/.cache/pip) and build directories persist between jobs and can poison later trusted release jobs. - Approval setting gap: "Require approval for all external contributors" gates only
pull_request, notpull_request_target. - Explicit opt-in:
allow-unsafe-pr-checkout: truere-enables untrusted fork checkouts.
Remediation
- Update SHA-pinned
actions/checkoutrefs to the patched releases. - Pass untrusted input through environment variables, never
${{ }}interpolation. - For
issue_commentandrepository_dispatch, verify the actor's real permission, check out the exact head SHA, and validate payloads against an allowlist. - Treat artifacts from less-trusted runs as untrusted data and never execute them.
- Use ephemeral runners and separate runner groups for untrusted and trusted workflows.
- Put privileged jobs behind environments with required reviewers or Workflow Execution Protections actor rules.
- Before December 2, review policy insights, move workflows to
pull_requestwhere possible, and allowlist only audited files in an explicit event policy. - Audit with zizmor, Wiz Code or the grep and SHA-resolution scripts provided in the article.
- SHA pinning paradox: the protections are backported into