CalcHub

GitHub Actions Security Audit — Top-5 Workflow Risks

Paste a GitHub Actions workflow YAML and catch the top-5 CI/CD risks: unpinned actions, script injection, pull_request_target abuse, secrets in run steps and write-all permissions.

Waiting
Paste content above
The tool runs instantly, entirely in your browser.

Last reviewed 2026-10-19. Rates change — verify against the official sources linked below before relying on these figures.

What this is based on

  • Checks: actions not pinned to a full commit SHA, github.event.* interpolated into run: (script injection), secrets referenced inside run steps, permissions: write-all, and pull_request_target combined with checkout of PR head.
  • Everything runs locally in your browser — pasted content is never uploaded, logged or stored.

Why unpinned actions are fail-level

uses: actions/checkout@v4 trusts whoever controls that tag. Tags can be moved — a compromised action maintainer (or a supply-chain attacker) can repoint v4 at malicious code, and your next run silently executes it with your repo's tokens and secrets. Pinning to a full commit SHA makes the code immutable; Dependabot can still bump it.

The 2025 tj-actions compromise hit exactly this pattern — moved tags executing credential-theft code in thousands of pipelines.

The pull_request_target trap

pull_request_target runs the workflow from the base repo — with its secrets and write token — but it can still check out and run code from the attacker's fork. Anyone can open a PR; if your job does actions/checkout with the PR head SHA and then executes it, you've handed a stranger your secrets.

The safe patterns: use pull_request for untrusted code, or split the workflow — a privileged job that never checks out PR code, and an unprivileged one that does.

Frequently asked questions

Is ${{ secrets.X }} in a run step always bad?
Interpolation into the shell means the value appears in the process command line and can be echoed into logs. Passing it via env: keeps it out of the command string — safer, though the real fix for cloud access is OIDC.
My action is from github.com/actions — still needs pinning?
First-party actions are lower-risk, but pinning everything is simpler than maintaining a trust list — and it protects you if a repo is transferred.
Does this parse YAML?
It's a line-based pattern audit, not a full YAML parser — the same checks the open-source CLI runs. Multiline run: blocks get caught by the pull_request_target and injection heuristics.

Related calculators