Skip to content
Hidden Logic Lab

Scan GitHub Actions workflows for secret exfil before merge

Cursor or Claude Code applies a SKILL.md on workflow PRs: hunt secret exfiltration, pull_request_target misuse, unpinned actions, and overbroad permissions — with a merge gate comment.

·Coding·35 min·Working

A workflow-security SKILL.md referenced from CI docs, Block/Warn findings on every .github/workflows change, and no new exfil paths merged as YAML cleanup.

  1. 1

    Run on a recent workflow PR

    Use a real diff, including bot bumps. The skill should catch unpinned actions your team policy forbids.

  2. 2

    Document fork PR policy beside the skill

    State whether fork workflows get secrets. The skill's pull_request_target rules must match GitHub repo settings.

  3. 3

    Require review for workflow changes

    Add CODEOWNERS on .github/workflows/ and link this SKILL.md in the PR template for CI edits.

The prompt to paste

Write SKILL.md for reviewing GitHub Actions workflow YAML before merge. Focus on secret theft, privilege escalation, and supply-chain drift — not general CI speed tuning.

Repository context:
[.github/workflows/ layout, default branch, fork PR policy]
[secret names used in workflows — names only, e.g. NPM_TOKEN, DEPLOY_KEY]
[whether pull_request_target is ever allowed and under what guardrails]

Workflow PR context (paste when using):
[PR link, changed workflow files, trigger type: pull_request vs pull_request_target vs workflow_dispatch]

SKILL.md must include:
1. Purpose — workflows run with repo secrets; a malicious or careless YAML change can exfiltrate them on fork PRs.
2. When to use — any PR touching .github/workflows/** or composite actions in-repo. When not to use — README badges only.
3. Hard rules for findings:
   - Block: pull_request_target checking out untrusted PR head and running scripts with secrets; secrets.* echoed to logs or sent to curl/wget/webhook; workflow_run from untrusted forks with write permissions; uses: unpinned third-party action on @main or moving tag (@v4 without sha pin if your policy requires sha).
   - Warn: permissions: write-all or contents: write without justification; reusable workflow callable from external repos without ref pin; artifact upload steps that include env dumps; missing permissions: block at workflow level (defaults too broad on org).
   - Note: stylistic YAML, cache key tweaks, runner label changes with no secret access.
4. Review steps the agent must execute:
   - List each workflow's on: triggers and whether fork PRs can reach it.
   - Map every step that references secrets.* or id-token write — trace data flow to network steps (curl, gh api posting off-repo, HTTP request actions).
   - Flag pull_request_target + checkout of PR code; require alternative pattern or human security ack [define team pattern or placeholder].
   - For each uses: line, record action@ref; flag unpinned or deprecated actions (checkout@v1, set-output shell patterns).
   - Check permissions: block at job level where possible; compare to least privilege.
   - Verify fork PRs cannot approve/deploy via workflow_dispatch abuse [describe repo settings checklist].
5. PR comment template: severity counts, findings table (file:line — issue — evidence), Merge recommendation.
6. Safe patterns section: pull_request + workflows that do not need secrets on fork PRs; optional approval gate for pull_request_target if team requires it.
7. Two example prompts: innocuous cache bump vs fork-opened PR adding curl exfil step.
8. Pitfalls: assuming private repo means safe forks, trusting action major tags without reading release notes, missing composite action in .github/actions, disabling secret scanning because tests failed.
9. Done means: all Block resolved or PR rejected, Warns reviewed by someone with admin context, no secret values pasted in review comment, actions pinned per team policy.

Rules:
- Never print secret values; reference ${{ secrets.NAME }} by name only.
- Do not suggest disabling branch protection to test workflows.
- Output only SKILL.md markdown.

pull_request_target with checkout of the PR branch is the classic secret exfil footgun. The skill should Block first and only allow exceptions with a named security approver in the PR.

Sample case written by Hidden Logic Lab. Not affiliated with Cursor or Claude Code or GitHub.

More in Coding

Get new cases in your inbox

Weekly notes on new use cases and agent workflows. No product pitches.

Occasional notes on new cases. No product pitches in the first note.