Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Trigger Rules (200s)

Dangerous trigger configurations expose workflows to attacks from untrusted contributors. The pull_request_target event is particularly hazardous because it runs in the context of the base repository with full access to secrets, even when triggered by a fork.


WRD-201: Dangerous Fork Checkout

Severity: Critical

What it detects: A workflow triggered by pull_request_target that checks out the pull request’s head code (via ref: ${{ github.event.pull_request.head.sha }} or github.head_ref), combining privileged execution context with attacker-controlled code.

Vulnerable:

on: pull_request_target

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2
        with:
          ref: ${{ github.event.pull_request.head.sha }}
      - run: npm install && npm test

This pattern is known as a “pwn request.” An attacker submits a PR that modifies npm test or package.json scripts and gains code execution with the base repository’s secrets.

Remediation: Use pull_request instead of pull_request_target, or avoid checking out untrusted code. If checkout is necessary, do not run any build/test commands on the checked-out code.

# Unprivileged workflow: runs fork code, no secrets
on: pull_request
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2
      - run: npm install && npm test

WRD-202: Build Tool Execution on Untrusted Code

Severity: Critical

What it detects: A pull_request_target workflow that checks out the PR head and then executes build tools (npm, pip, cargo, make, yarn, gradle, mvn, go, poetry, etc.) on the untrusted code. This is a more specific variant of WRD-201 that looks for actual build commands.

Vulnerable:

on: pull_request_target

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2
        with:
          ref: ${{ github.event.pull_request.head.ref }}
      - run: npm install && npm test

An attacker can modify build scripts, package.json lifecycle hooks, or Makefile targets in their fork to execute arbitrary code with elevated privileges.

Remediation: Split into two workflows. Run build tools only in unprivileged pull_request workflows. Use workflow_run for privileged operations that do not run fork code.


WRD-203: Cross-Workflow Privilege Escalation

Severity: Critical

What it detects: A workflow_run-triggered workflow with write permissions or that downloads artifacts. If the producing workflow is triggered by pull_request, an attacker can poison artifacts in a fork PR to escalate privileges.

Vulnerable:

on:
  workflow_run:
    workflows: ["CI"]
    types: [completed]

permissions:
  contents: write

jobs:
  publish:
    steps:
      - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c  # v8.0.1
        with:
          run-id: ${{ github.event.workflow_run.id }}
      - run: ./deploy.sh $(cat artifact/target.txt)

Remediation: Minimize permissions on workflow_run workflows. Validate artifact integrity before use. Check github.event.workflow_run.conclusion and fork status before processing.

jobs:
  publish:
    if: github.event.workflow_run.conclusion == 'success'
    steps:
      - name: Check workflow origin
        run: |
          if [[ "${{ github.event.workflow_run.head_repository.fork }}" == "true" ]]; then
            echo "Refusing artifact from fork" && exit 1
          fi