Securing your CI/CD pipelines
The CI/CD pipeline: a high-value target
Your CI/CD pipeline has access to everything: source code, secrets, production credentials, signing keys. A compromised pipeline does not just affect one system — it poisons every artifact you ship. It is one of the highest-value targets in your infrastructure.
This is not a theoretical concern. The SolarWinds attack was fundamentally a CI/CD compromise: attackers inserted malicious code into the build process, which was then compiled into the legitimate Orion software and distributed to customers through the official update channel. The Codecov breach gave attackers access to CI/CD environment variables in thousands of customer pipelines. Every organization that builds and deploys software has a pipeline attack surface.
The unique danger of CI/CD compromise is its multiplier effect: a single compromise affects every artifact produced and every downstream environment those artifacts reach. A supply chain attack through CI/CD effectively achieves persistent access to every system that runs the compromised software.
Primary risks
- Workflow file injection: a malicious contributor modifies a workflow file to execute arbitrary code during builds
- Exposed secrets: environment variables, tokens, and API keys accessible in build logs or via compromised steps
- Compromised build dependencies: infected GitHub Actions, Jenkins plugins, or third-party orbs
- Shared runners: a compromised shared runner affects every project using it
Workflow file injection is a particular concern for open source projects or organizations that accept pull requests from external contributors. GitHub Actions workflows can be triggered by pull requests from forked repositories. If a workflow grants excessive permissions or accesses secrets without proper conditions, a malicious pull request can steal secrets or execute attacker-controlled code in the pipeline context.
Secret sprawl in CI/CD environments is common. Over time, pipelines accumulate credentials: database passwords, API keys, deployment tokens, signing certificates. These are often stored in plaintext environment variables, shared across multiple projects, and never rotated because rotation requires coordinating changes across multiple pipeline configurations.
Action/plugin supply chain attacks target the third-party steps that build pipelines depend on. When a pipeline references actions/checkout@v3 or a Jenkins plugin, it trusts that third-party code completely. If an attacker compromises an action’s repository or uploads a malicious plugin update, every pipeline using that action is potentially compromised. Pinning actions to specific commit hashes (rather than version tags) prevents tag-based attacks but adds maintenance overhead.
Essential controls
Secret management:
- Use a dedicated vault (HashiCorp Vault, AWS Secrets Manager) instead of plain environment variables
- Rotate secrets regularly and on personnel changes
- Never log secrets; mask them in build output
Secret management in CI/CD should follow the same principles as application secret management: secrets are injected at runtime from a vault, not stored in pipeline configurations. Dynamic secrets (credentials generated on demand and automatically expired after use) further limit exposure by ensuring no long-lived credentials exist to steal.
Build isolation:
- Use ephemeral runners (destroyed after each build) to prevent cross-build contamination
- Isolate production builds from development and test builds
- Restrict runner permissions to the strict minimum required for each job
Ephemeral runners are a particularly high-value control. Persistent runners accumulate state: credentials cached by tools, build artifacts, environment state from previous builds. An attacker who compromises a persistent runner can potentially access data from previous or future builds. Ephemeral runners start from a clean image for each build, eliminating this risk.
Integrity verification:
- Sign build artifacts (cosign, Sigstore) to establish a chain of custody
- Verify checksums of all build dependencies before use
- Pin all dependencies with lock files (package-lock.json, Pipfile.lock, go.sum)
Artifact signing creates a verifiable record that an artifact was produced by an authorized pipeline. Deployment systems can verify the signature before installing artifacts, detecting any modification after signing. Sigstore’s keyless signing model makes this practical at scale without the complexity of traditional certificate management.
Audit and monitoring:
- Review all workflow file modifications before merging
- Alert on additions of new actions, plugins, or external dependencies
- Audit CI/CD token permissions and revoke unused access regularly
Reviewing workflow file modifications is critical because pipelines are code — and pipeline code changes can introduce security vulnerabilities just as application code changes can. Many organizations apply rigorous code review to application code while treating pipeline configuration as administrative boilerplate. Requiring security team review for pipeline changes, especially changes that add new external dependencies or modify secret access, is a high-value control.
SLSA framework
The Supply chain Levels for Software Artifacts (SLSA) framework provides a graduated set of requirements for supply chain security, from basic build integrity (Level 1) through provenance verification (Level 2), fully isolated builds (Level 3), and two-person review requirements (Level 4).
SLSA gives organizations a structured roadmap for improving CI/CD security incrementally, with clear milestones that correspond to specific threats mitigated. It also provides a common language for communicating security posture to customers, auditors, and regulators.
Most organizations currently operate at SLSA Level 0 or 1. Targeting SLSA Level 2 — which requires signed provenance records for every build — is a practical near-term goal that significantly raises the bar for supply chain attacks.
Advertisement