Why pipelines deserve the same scrutiny as production
A modern build pipeline has access to:
- Production deploy keys
- Cloud provider credentials
- Package registry tokens
- Source code signing keys
- Customer database read access (in some flows)
If an attacker compromises CI, they own production. Yet most pen-tests stop at the application layer.
The 12-point checklist
- Branch protection — main protected, required reviews, no force-push
- Required CI checks — security scans + tests must pass before merge
- Workflow review — no
workflow_dispatchfrom untrusted forks - Pinned actions — every third-party action pinned to a SHA, not a tag
- Secret scoping — least-privilege scopes, environment-scoped where supported
- OIDC for cloud — short-lived federated credentials over long-lived keys
- Self-hosted runner isolation — ephemeral runners, never reused across jobs
- Artifact signing — releases signed with a key not stored in CI
- Dependency provenance — SBOM generated, supply-chain attacks detected
- Audit logs — pipeline runs logged to immutable storage
- Approval gates — production deploys require human approval
- Disaster recovery — pipeline can be rebuilt from source in under an hour
What we typically find
- Pinned to a tag, not a SHA — 60% of teams
- Long-lived AWS keys in secrets — 40%
- No SBOM — 75%
- Self-hosted runners reused across jobs — 30%
- Production deploy without approval — 20%
None of these are exotic. Closing them takes a sprint.
// tags:
#ci/cd
#supply chain
#devops