9.5.1. CI/CD Pipeline Security
💡 First Principle: A CI/CD pipeline is a supply chain — code enters at one end, and a deployable artifact exits at the other. Every stage of the pipeline is an opportunity to inject security verification, but also an opportunity for an attacker to inject malicious code if the pipeline itself is not secured. Pipeline security means both securing the artifacts flowing through the pipeline (scanning code and dependencies) and securing the pipeline infrastructure itself (build servers, credentials, artifact storage).
Security controls at each pipeline stage:
| Stage | Security Control | What It Catches |
|---|---|---|
| Pre-commit | IDE security plugins, pre-commit hooks, secret scanning | Hardcoded secrets, obvious vulnerabilities before code enters repo |
| Commit/PR | SAST, SCA, license scanning, code review | Injection flaws, vulnerable dependencies, licensing issues |
| Build | Container image scanning, SBOM generation, dependency verification | Vulnerable base images, dependency integrity, supply chain issues |
| Test | DAST, IAST, security integration tests, fuzzing | Runtime vulnerabilities, authentication bypasses, input handling bugs |
| Deploy | Configuration scanning, infrastructure-as-code validation, policy checks | Misconfigurations, policy violations, insecure defaults |
| Runtime | RASP, WAF, monitoring, anomaly detection | Active exploitation, zero-day attacks, behavioral anomalies |
Pipeline infrastructure security:
- Build server isolation — Build servers should be ephemeral (created fresh for each build, destroyed after) to prevent persistent compromise. A compromised build server that persists across builds can inject malicious code into every subsequent artifact.
- Secret management — Credentials needed during build (API keys, signing certificates, deployment credentials) must be stored in a secrets manager (HashiCorp Vault, AWS Secrets Manager) and injected at runtime — never hardcoded in pipeline configuration files.
- Pipeline-as-code security — Pipeline definitions (Jenkinsfile, GitHub Actions workflows, GitLab CI YAML) are code and must be protected with the same rigor as application code: version control, code review, restricted modification permissions.
- Artifact integrity — Built artifacts should be signed. Deployment processes should verify signatures before deploying. This creates an unbroken chain of trust from source code to production.
SLSA (Supply-chain Levels for Software Artifacts):
SLSA defines four maturity levels for build integrity:
| Level | Requirement | What It Proves |
|---|---|---|
| SLSA 1 | Build process documented | You know how artifacts are produced |
| SLSA 2 | Build service used (not developer laptop); provenance generated | Builds are reproducible and traceable |
| SLSA 3 | Hardened build platform; verified provenance | Build environment resists tampering |
| SLSA 4 | Hermetic, reproducible builds; two-person review | Highest assurance; detects build-time tampering |
⚠️ Exam Trap: Secrets (API keys, database passwords, signing certificates) committed to version control are exposed permanently — even if deleted in a subsequent commit. Git history preserves every previous version of every file. A secret committed and then "deleted" is still accessible to anyone who can clone the repository and examine history. Secret scanning must check not just the current state but the full commit history.
Reflection Question: A post-incident review reveals that an attacker gained access to the organization's Jenkins build server, modified a build script to inject a cryptominer into the application binary, and the modified binary was automatically deployed to production through the CI/CD pipeline. No alerts were triggered. Identify the pipeline security controls that were missing, describe the architectural changes needed to prevent this attack class, and explain how SLSA Level 3 requirements would have detected the compromise.