Workflow Audit

SkillSecurity

Lets your agent audit GitHub Actions workflow files for bugs, security holes, and reliability problems.

Available today. Use it from your connected AI after setup.

Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.

Then ask your AI: use the Workflow Audit skill

About this skill

Audit GitHub Actions workflows for correctness, security, and unattended reliability. Use when asked to audit workflows, check CI health, review workflow security, or before committing workflow changes.

What this skill tells your AI

The instructions your AI receives, as published by xiaolai/vmark in .claude/skills/workflow-audit/SKILL.md and read by ahel’s review.

Comprehensive audit of .github/workflows/*.yml files against GitHub Actions best practices, security hardening guidelines, and project conventions.

When to Use

  • User asks to audit, review, or check workflows
  • Before committing changes to any workflow file
  • After a workflow failure that needs root-cause analysis
  • Periodic health check (e.g., monthly)

Workflow

  1. Discover — Glob .github/workflows/*.yml and list all workflow files.
  2. Parse — Read each file; validate YAML syntax.
  3. Audit — Run every check in the checklist below against each file.
  4. Cross-check — Run cross-workflow consistency checks.
  5. Report — Output a findings table sorted by severity (critical > high > medium > low).
  6. Fix offer — For each finding, suggest a concrete fix (diff or instruction).

Audit Checklist

1. YAML Validity

  • File parses as valid YAML.
  • No duplicate keys at the same level.
  • No tabs (GitHub Actions requires spaces).

2. Action Version Currency

Check every uses: line.

PatternSeverityRule
actions/checkout@v4 or lowercriticalUpgrade to @v6. Node.js 20 actions break June 2, 2026 (forced to Node 24).
actions/setup-node@v4 or lowercriticalSame — upgrade to @v6.
actions/cache@v3 or lowerhighUpgrade to @v4.
pnpm/action-setup@v3 or lowerhighUpgrade to @v4.
softprops/action-gh-release@v1mediumUpgrade to @v2.
actions/upload-pages-artifact@v2 or lowermediumUpgrade to @v3.
actions/deploy-pages@v3 or lowermediumUpgrade to @v4.
Any @main or @master pinhighPin to a tag or SHA — mutable refs are a supply-chain risk.

Node.js deprecation timeline (reference for findings):

  • June 2, 2026: Node 24 becomes default (FORCE_JAVASCRIPT_ACTIONS_TO_NODE24=true to opt in early).
  • Fall 2026: Node 20 removed entirely from runners.
  • Temporary opt-out after June 2: ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION=true (stops working fall 2026).

3. Security — Script Injection

For every run: block, check for untrusted context expressions used inline:

# DANGEROUS — attacker-controlled input interpreted by shell
run: echo "${{ github.event.issue.title }}"

# SAFE — passed via environment variable
env:
  TITLE: ${{ github.event.issue.title }}
run: echo "$TITLE"

Untrusted contexts (must NEVER appear directly in run: blocks):

  • github.event.issue.title / .body
  • github.event.pull_request.title / .body
  • github.event.comment.body
  • github.event.review.body / github.event.review_comment.body
  • github.event.commits.*.message
  • github.event.head_commit.message / .author.email / .author.name
  • github.event.pull_request.head.ref / .head.label / .head.repo.default_branch
  • github.head_ref
  • github.event.pages.*.page_name

Safe contexts (numeric or system-controlled, OK inline):

  • github.event.issue.number, github.event.pull_request.number
  • github.repository, github.run_id, github.sha
  • github.ref (only on push/tag events, not PR)
  • secrets.*, env.*, matrix.*

4. Security — Permissions

CheckSeverityRule
No permissions: block at allhighAdd explicit permissions — defaults give broad access.
permissions: write-allcriticalNever use. Specify individual scopes.
Unused permission scopesmediumRemove permissions not needed by any step.
id-token: write without OIDC usagemediumOnly needed for Bedrock/Vertex/Foundry or cloud OIDC.
pull_request_target triggerhighGrants write access from forks — verify checkout uses PR base, not head.

5. Security — Auto-merge and Bot Patterns

CheckSeverityRule
gh pr merge --auto without author guardhighRestrict to bot PRs: if: github.event.pull_request.user.login == 'claude[bot]'
allowed_bots: '*' in claude-code-actionmediumPrefer explicit bot names over wildcard.

6. Reliability — Timeouts

CheckSeverityRule
Job without timeout-minuteshighDefault is 360 min (6 hours). Always set explicit timeouts.
Claude Code action jobshighMust have timeout-minutes (recommended: 15 for review, 30 for fix).
Build jobsmediumRecommended: 30-45 min depending on platform.

7. Reliability — Error Handling

CheckSeverityRule
git push to a protected branchcriticalWill fail if branch protection requires status checks. Push to unprotected branch or use PR.
gh pr merge without || true or continue-on-errormediumMay fail if PR is not mergeable — handle gracefully.
Steps after a continue-on-error step that depend on its outputmediumCheck if downstream steps handle the soft failure.
Network-dependent steps without retry or continue-on-errorlowCDN downloads, API calls can be flaky.

8. Reliability — Concurrency

CheckSeverityRule
Scheduled workflow without concurrency groupmediumOverlapping runs waste resources.
cancel-in-progress: true on deploy workflowshighCan corrupt partial deployments. Use false for deploys.
Missing concurrency on Claude Code jobsmediumMultiple concurrent AI runs on the same issue/PR waste credits.

9. Reliability — Branch Protection Awareness

CheckSeverityRule
Workflow pushes to main (or default branch)criticalCheck if branch protection allows this. Use a data branch or PR workflow.
Workflow creates commits without checking git diff firstmediumMay create empty commits or fail on no-changes.

10. Cross-Workflow Consistency

CheckSeverityRule
Different node-version across workflowshighAll workflows should use the same Node.js version (currently 22).
Different pnpm version across workflowshighAll workflows should use the same pnpm version (currently 10).
Different Rust toolchain specificationmediumShould be consistent unless intentionally testing multiple versions.
Duplicate triggers (same event in multiple workflows)mediumCan cause double-execution. Verify intentional.

11. Claude Code Action — Configuration

Reference: anthropics/claude-code-action@v1

CheckSeverityRule
Using @beta or @v0criticalMigrate to @v1. v0.x inputs are deprecated.
Using deprecated inputs (direct_prompt, model, allowed_tools, max_turns, timeout_minutes)highMigrate to prompt + claude_args.
Missing claude_code_oauth_token or anthropic_api_keycriticalOne auth method is required.
--model not specified in claude_argslowDefaults to action's default model. Specify for reproducibility.
--max-turns not specified for fix/implementation jobsmediumUnbounded turns burn credits. Recommend 15-25 for fixes.
show_full_output: true on review jobslowVerbose — only needed for debugging.

Key claude_args flags:

  • --model <model-id> — e.g., claude-opus-4-6, claude-sonnet-4-6
  • --max-turns <N> — limit conversation turns
  • --allowedTools <tool1>,<tool2> — restrict tool access
  • --disallowedTools <tool1> — block specific tools
  • --system-prompt "..." — custom system prompt

Authentication options:

  • anthropic_api_key — direct Anthropic API
  • claude_code_oauth_token — Claude Code OAuth (subscription-based)
  • use_bedrock: true + OIDC — Amazon Bedrock
  • use_vertex: true + OIDC — Google Vertex AI

12. Trigger Hygiene

CheckSeverityRule
release: [published] + workflow_dispatch for same logicmediumChoose one trigger path to avoid double-execution.
push: branches: [main] on workflows that also have pull_requestlowIntentional for CI — but verify both are needed.
Scheduled workflow that only runs on default branchlowVerify schedule cron syntax with crontab.guru.
Workflow with no paths filter on push triggerlowConsider adding paths: to avoid unnecessary runs.

Report Format

Output a markdown table:

## Workflow Audit Report

| # | Severity | File | Check | Finding | Fix |
|---|----------|------|-------|---------|-----|
| 1 | critical | ci.yml | Action versions | `actions/checkout@v4` — Node 20 deprecated | Upgrade to `@v6` |
| 2 | high | claude.yml | Auto-merge | Enabled for all PRs | Add `if: github.event.pull_request.user.login == 'claude[bot]'` |

After the table, add a Summary line: X critical, Y high, Z medium, W low findings across N workflow files.

Notes

  • Do NOT modify workflow files during audit — report only.
  • When the user asks to fix findings, apply changes and re-audit to verify.
  • For security findings, always explain the attack vector (not just the rule).
  • Check .github/workflows/ only — ignore .github/actions/ unless referenced.

Signals

GitHub stars
808
Forks
127
Last commit
Sep 2026
Advanced
Item type
skill
Key
workflow-audit-xiaolai
Source
github.com/xiaolai/vmark