| Field | Value |
|---|
| Category | CICD-SEC-1 |
| Severity | HIGH |
| OWASP | CICD-SEC-1: Insufficient Flow Control |
| Auto-fix | ✓ (what it does) |
What the check does
Flags any workflow that:
- Triggers on a privileged event —
pull_request_target or workflow_run, and
- Uses
actions/checkout with ref: referencing the untrusted head: github.event.pull_request.head, github.head_ref, refs/pull/…, or github.event.workflow_run.head….
The trigger detection handles all three forms of on: — scalar, sequence, and mapping.
Why it’s dangerous
pull_request_target and workflow_run run in the context of the base branch with repository secrets and write permissions. If you then check out the PR’s head ref and run tests, builds, or any user-controlled script, an attacker who opens a PR can execute arbitrary code with elevated privileges and exfiltrate secrets.
Vulnerable example
name: ci
on: pull_request_target
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }} # ← untrusted code
- run: npm test # ← runs with secrets
Safe alternatives
- Use the standard
pull_request trigger instead. It runs in the PR’s own context and doesn’t expose secrets.
- If you must use
pull_request_target (e.g. to label PRs from forks), don’t check out the head ref — operate only on metadata.
- For workflows that need to run user code against secrets (rare), gate the job on
if: github.event.pull_request.head.repo.full_name == github.repository so it skips forks.
Auto-fix
--fix rewrites the trigger from pull_request_target to pull_request. It handles scalar, sequence, and mapping forms. If pull_request is already in the trigger list, the pull_request_target entry is removed. Findings from the workflow_run variant are flag-only — switching that trigger isn’t a safe mechanical rewrite, so they require manual remediation.
The auto-fix changes the trigger but does not remove the checkout-of-head step — the underlying code is no longer dangerous because the workflow now runs in the PR’s context, but review the diff to confirm the change matches your intent.