Key Takeaways
- CI/CD pipelines are high-value attack targets.
- Never store secrets in code or pipeline configs.
- Limit pipeline permissions to least privilege.
- Require approval for production deployments.
- Secure build runners and environments.
- Audit pipeline changes and executions.
Table of Contents
1. CI/CD Security Risks
CI/CD pipelines have privileged access to source code, secrets, production environments, and deployment infrastructure. A compromised pipeline can inject malicious code into every release, steal secrets, or provide persistent access to production systems.
Recent attacks (SolarWinds, Codecov) demonstrate the impact of compromised build processes. Securing CI/CD is critical for software supply chain security.
2. Secrets Management
2.1 Never Hardcode Secrets
# BAD - Never do this:
env:
API_KEY: "sk-1234567890abcdef"
# GOOD - Use secrets management:
env:
API_KEY: ${{ secrets.API_KEY }}
# BETTER - Use vault integration:
env:
API_KEY: ${{ steps.vault.outputs.api_key }}
2.2 Secrets Best Practices
- Use platform secrets (GitHub Secrets, GitLab CI Variables)
- Integrate with secrets managers (Vault, AWS Secrets Manager)
- Rotate secrets regularly
- Scope secrets to specific environments/jobs
- Never log secrets—mask in output
Secrets in Pull Requests
Be careful with secrets in forks/PRs. Attackers can submit PRs that exfiltrate secrets. Use environment protections, require approval for PRs from forks, and limit secrets exposed to PR builds.
3. Runner Security
- Use ephemeral runners: Fresh environment each build
- Harden runner images: Minimal, patched, monitored
- Isolate runners: Network segmentation, separate from production
- Self-hosted runners: Extra care—don't run untrusted code
# GitHub Actions - Use ephemeral self-hosted runners
# AWS CodeBuild - Ephemeral by design
# GitLab - Use Docker-in-Docker or Kubernetes runners
4. Permission Management
| Principle | Implementation |
|---|---|
| Least Privilege | Minimal permissions for each job |
| Require Approval | Manual approval for production deploys |
| Branch Protection | Require reviews, signed commits |
| Environment Protection | Restrict who can deploy to production |
# GitHub Actions - Restrict token permissions
permissions:
contents: read
pull-requests: write
# Only what's needed
5. Supply Chain Security
- Pin action/step versions by SHA, not tag
- Verify third-party actions before use
- Use dependency lockfiles
- Sign artifacts and verify signatures
- Generate and verify SBOMs
# PIN by SHA - not tag
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
# Not: uses: actions/checkout@v3 # Tags can be moved
6. Platform-Specific Guidance
GitHub Actions
- Use GITHUB_TOKEN with minimal scopes
- Enable Dependabot for action updates
- Require approval for workflows from forks
- Use OpenID Connect for cloud authentication
GitLab CI
- Use protected variables for sensitive data
- Protected branches for production
- Masked variables in logs
Jenkins
- Keep Jenkins and plugins updated
- Use credentials plugin, not plaintext
- Limit who can configure jobs
- Enable audit logging
7. Monitoring & Auditing
# What to monitor:
- All pipeline executions
- Configuration changes
- Secret access
- Failed authentication
- Unusual patterns (off-hours deploys, new contributors)
# Audit requirements:
- Immutable logs
- Retention policy
- Alert on anomalies
Defense in Depth
No single control is sufficient. Combine secrets management, permission controls, runner hardening, supply chain verification, and monitoring. Each layer catches what others miss.
8. Frequently Asked Questions
Conclusion
CI/CD pipeline security is critical for software supply chain safety. Protect secrets with proper management, secure runners, apply least privilege, verify supply chain integrity, and monitor everything. A compromised pipeline can undermine all other security controls—treat it as a high-value asset.
Continue Learning:
DevSecOps Guide
Git Security