Safeguard
Security Guides•

Which triggers in a copied workflow need a second look?

Most CI templates use push and pull_request. Triggers like pull_request_target and workflow_run run with more privilege and need care when copied.

Safeguard Security Team
3 min read

Push and pull_request are the ordinary triggers. Treat pull_request_target and workflow_run as privileged. They can run with repository secrets and write access, and GitHub warns against combining them with a checkout of untrusted pull request code. If a template you copied uses either one, read it twice.

The ordinary triggers

Most starter workflows run on push and pull_request for the default branch. For a pull request from a fork, GitHub's documentation says workflows run on the base repository event, and workflows triggered from a fork with the pull_request event have read only permissions and no access to secrets. That is the safe baseline for building and testing contributed code.

pull_request_target

This event runs in the context of the default branch of the base repository, rather than the merge commit. According to the events reference, that design prevents execution of unsafe code from the head of the pull request that could alter your repository or steal secrets. It exists so a workflow can do things such as label or comment on pull requests from forks.

The same page says to avoid this event if you need to build or run code from the pull request. The secure use guide adds that workflows with this trigger must not explicitly check out untrusted code, including from forks. A copied workflow that does pull_request_target plus a checkout of the pull request head is the pattern to catch.

workflow_run

This trigger starts a workflow after another one finishes. GitHub describes it as a better choice than pull_request_target for privilege separation, but treats it with the same caution: the privileged workflow should handle artifacts from the other workflow carefully, because that content may come from an untrusted pull request. See separating privileged workflows with workflow_run.

Other triggers to read twice

GitHub's compromised runners page lists events where secrets and write permissions are in play, including issue_comment, issues, push, and pull_request from a branch inside the repository. These run with more authority than a fork pull request does, so any script step reacting to user supplied text needs care.

A triage table

TriggerRuns in context ofSecrets and write accessCopy rule
pull_request (fork)Merge commitRead only, no secretsFine for build and test
pull_request_targetDefault branchCan be availableNever check out untrusted code
workflow_runDefault branchCan be availableTreat artifacts as untrusted
issue_comment, issuesDefault branchCan be availableNever put text into shell lines

What to do with a template that uses one

  1. Ask whether the workflow needs the privileged context at all. Often it does not.
  2. If it does, remove any checkout of pull request head code.
  3. Put untrusted values in environment variables, never inline in scripts.
  4. Add CODEOWNERS on the workflows directory.
  5. Let a scanner such as CodeQL or OpenSSF Scorecard check for dangerous patterns. GitHub's guide mentions both.

Quick check

Is pull_request_target always unsafe?

No. It is intended for tasks like labelling. It becomes dangerous when combined with checking out or running code from the pull request.

Do first time contributors trigger these automatically?

For public repositories, GitHub may require a maintainer with write access to approve workflow runs from a first time contributor's pull request.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.