Find exploitable vulnerabilities in GitHub Actions workflows. Every finding MUST include a concrete exploitation scenario — if you can't build the attack, don't report it.
This skill encodes attack patterns from real GitHub Actions exploits — not generic CI/CD theory.
Review the workflows provided (file, diff, or repo). Research the codebase as needed to trace complete attack paths before reporting.
.github/workflows/*.yml — all workflow definitionsaction.yml / action.yaml — composite actions in the repo.github/actions/*/action.yml — local reusable actionsCLAUDE.md, AGENTS.md, Makefile, shell scripts under .github/
Only report vulnerabilities exploitable by an external attacker — someone without write access to the repository. The attacker can open PRs from forks, create issues, and post comments. They cannot push to branches, trigger workflow_dispatch, or trigger manual workflows.
Do not flag vulnerabilities that require write access to exploit:
workflow_dispatch input injection — requires write access to triggerpush-only workflows on protected branchesworkflow_call input injection where all callers are internalworkflow_dispatch/schedule-only workflowsReport only HIGH and MEDIUM confidence findings. Do not report theoretical issues.
| Confidence | Criteria | Action |
|---|---|---|
| HIGH | Traced the full attack path, confirmed exploitable | Report with exploitation scenario and fix |
| MEDIUM | Attack path partially confirmed, uncertain link | Report as needs verification |
| LOW | Theoretical or mitigated elsewhere | Do not report |
For each HIGH finding, provide all five elements:
If you cannot construct all five, report as MEDIUM (needs verification).
For each workflow, identify triggers and load the appropriate reference:
| Trigger / Pattern | Load Reference |
|---|---|
pull_request_target |
references/pwn-request.md |
issue_comment with command parsing |
references/comment-triggered-commands.md |
${{ }} in run: blocks |
references/expression-injection.md |
| PATs / deploy keys / elevated credentials | references/credential-escalation.md |
| Checkout PR code + config file loading | references/ai-prompt-injection-via-ci.md |
| Third-party actions (especially unpinned) | references/supply-chain.md |
permissions: block or secrets usage |
references/permissions-and-secrets.md |
| Self-hosted runners, cache/artifact usage | references/runner-infrastructure.md |
| Any confirmed finding | references/real-world-attacks.md |
Load references selectively — only what's relevant to the triggers found.
Does the workflow use pull_request_target AND check out fork code?
actions/checkout with ref: pointing to PR head./.github/actions/) that would come from the forkrun: step executes code from the checked-out PRAre ${{ }} expressions used inside run: blocks in externally-triggerable workflows?
${{ }} expression in every run: steprun: block, not if:, with:, or job-level env:
Does an issue_comment-triggered workflow execute commands without authorization?
author_association check?Are elevated credentials (PATs, deploy keys) accessible to untrusted code?
Does the workflow load configuration from PR-supplied files?
CLAUDE.md, AGENTS.md, .cursorrules
Makefile, shell scriptsAre third-party actions securely pinned?
Are workflow permissions minimal? Are secrets properly scoped?
Are self-hosted runners, caches, or artifacts used securely?
Before reporting, check if the pattern is actually safe:
| Pattern | Why Safe |
|---|---|
pull_request_target WITHOUT checkout of fork code |
Never executes attacker code |
${{ github.event.pull_request.number }} in run: |
Numeric only — not injectable |
${{ github.repository }} / github.repository_owner |
Repo owner controls this |
${{ secrets.* }} |
Not an expression injection vector |
${{ }} in if: conditions |
Evaluated by Actions runtime, not shell |
${{ }} in with: inputs |
Passed as string parameters, not shell-evaluated |
| Actions pinned to full SHA | Immutable reference |
pull_request trigger (not _target) |
Runs in fork context with read-only token |
Any expression in workflow_dispatch/schedule/push to protected branches |
Requires write access — outside threat model |
Key distinction: ${{ }} is dangerous in run: blocks (shell expansion) but safe in if:, with:, and env: at the job/step level (Actions runtime evaluation).
Before including any finding, read the actual workflow YAML and trace the complete attack path:
if: conditions that gate executionrun: block or actually references fork codeIf any link is broken, mark MEDIUM (needs verification) or drop the finding.
If no checks produced a finding, report zero findings. Do not invent issues.
## GitHub Actions Security Review
### Findings
#### [GHA-001] [Title] (Severity: Critical/High/Medium)
- **Workflow**: `.github/workflows/release.yml:15`
- **Trigger**: `pull_request_target`
- **Confidence**: HIGH — confirmed through attack path tracing
- **Exploitation Scenario**:
1. [Step-by-step attack]
- **Impact**: [What attacker gains]
- **Fix**: [Code that fixes the issue]
### Needs Verification
[MEDIUM confidence items with explanation of what to verify]
### Reviewed and Cleared
[Workflows reviewed and confirmed safe]
If no findings: "No exploitable vulnerabilities identified. All workflows reviewed and cleared."