Goals:
- •Make workflows safer by default (least privilege, immutable dependencies, safe triggers)
- •Reduce supply-chain risk (pin actions, restrict third-party actions)
- •Prevent common GH Actions foot-guns (untrusted code execution, secret leaks, token over-scope)
Checklist:
- •Triggers & untrusted code
- •Prefer
pull_requestfor PR checks; avoidpull_request_targetunless you fully understand the risks - •If
pull_request_targetis required:- •Never checkout or execute untrusted PR code with elevated permissions
- •Run only trusted steps (labeling, commenting, policy checks) on base repo code
- •For forks:
- •Avoid granting secrets; use
pull_request+ read-only token where possible - •Consider
workflow_runpatterns for privileged post-merge actions
- •Avoid granting secrets; use
- •Permissions discipline (GITHUB_TOKEN)
- •Set workflow-level
permissions:to the minimum (oftencontents: read) - •Elevate per-job only when needed (e.g.,
pull-requests: write,packages: write,id-token: write) - •If using attestations: include
attestations: writeonly for the job that attests
- •Immutable dependencies (pinning)
- •Pin third-party actions to a full commit SHA (preferred immutable form)
- •Prefer first-party
actions/*and well-maintained verified publishers - •Avoid floating tags (
@v1,@main) for third-party actions in security-sensitive workflows
- •Secret safety
- •Never echo secrets; avoid
set -x/ verbose logging around secrets - •Use environments + required reviewers for production deploy secrets
- •Prefer OIDC to cloud providers over long-lived cloud keys/secrets
- •Runner & execution hardening
- •Add
timeout-minutesto jobs (avoid hung runners) - •Use
concurrencyto cancel redundant runs on same ref where appropriate - •Use
defaults.run.shell: bashand fail-fast practices in scripts (set -euo pipefailin multi-line steps) - •If using self-hosted runners: assume they are high-trust; isolate, patch, and prefer ephemeral runners for prod
- •Artifact & input trust
- •Treat artifacts from PR workflows as untrusted unless produced and consumed within the same trust boundary
- •Validate any external input: workflow_dispatch inputs, issue comments, PR titles/labels, etc.
- •Required security checks (when available)
- •Add Dependency Review on PRs that modify dependencies
- •Add CodeQL scanning for supported languages
- •Ensure branch protection required checks match workflow/job names exactly
Finish with:
- •A concise diff-style summary of what changed in the workflow(s)
- •Final permissions table (workflow-level + per-job)
- •Actions pinning changes (what got pinned and why)
- •Any remaining risks or follow-ups (branch protection, env reviewers, secrets/OIDC setup)