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.
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
Paste code or a git diff and detect leaked credentials — AWS keys, GitHub and Slack tokens, private key blocks, hardcoded API keys and JWTs. Matched values are masked, never displayed.
Paste a Dockerfile and get an instant security review: baked secrets, unpinned base images, root containers, curl-pipe-to-shell and remote ADD — all checked locally.
Paste your .env and .env.example to instantly find missing keys, empty values and undocumented extras. Values never leave your browser — only key names are compared.