CI/CD pipelines have become the critical path through which virtually all modern software is built, tested, and deployed. They are also one of the highest-value targets in the modern threat landscape. The 2020 SolarWinds supply chain compromise β in which malicious code was injected directly into a software build process and distributed to thousands of downstream customers β demonstrated conclusively that securing the pipeline itself is not optional. It is a foundational requirement for any team shipping software in production.
The good news: the security industry has responded with mature frameworks and practical controls. The challenge for most teams is knowing which controls to implement first and how to build security into a pipeline without crippling delivery velocity. This playbook covers both.
Why CI/CD Pipelines Are High-Value Targets
A CI/CD pipeline typically has access to production secrets, deployment credentials, cloud provider keys, container registries, and the ability to push code directly to production systems. If an attacker can compromise the pipeline β whether by injecting malicious code into a dependency, hijacking a third-party action, compromising a developer's credentials, or exploiting a misconfigured runner β they inherit all of that access. The blast radius of a pipeline compromise is often far larger than a traditional application-layer breach.
The OWASP CI/CD Security Top 10, first published in 2022 and maintained as a living document, identifies the most commonly exploited vulnerability classes in modern delivery pipelines. The top three β insufficient flow control mechanisms, inadequate identity and access management, and dependency chain abuse β account for the majority of real-world supply chain incidents. Understanding these categories is the prerequisite to any meaningful defense.
The SLSA Framework: A Principled Security Baseline
The Supply-chain Levels for Software Artifacts (SLSA, pronounced "salsa") framework, developed by Google and now stewarded by the Linux Foundation's OpenSSF project, provides a four-level maturity model for securing the software build process. It addresses two core questions that every team should be able to answer: can you prove where your software came from, and can you prove it wasn't tampered with between source and deployment?
SLSA levels progress from basic source control hygiene at Level 1 to fully hermetic, reproducible builds with comprehensive provenance attestation at Level 4. Most production teams should target SLSA Level 2 as a practical near-term goal, which requires a hosted build service generating provenance β a signed, verifiable record of what inputs went into a build and what the output was.
The Ten Controls That Matter Most
Drawing from the OWASP CI/CD Top 10 and established DevSecOps practice, we recommend implementing the following controls in rough priority order:
1. Least-privilege pipeline identities. Every CI/CD job should run with the minimum permissions needed for that specific job β and nothing more. A test job has no business with production deployment credentials. A build job should not have write access to the artifact registry if it only needs read access. Audit your pipeline's IAM configuration regularly and remove permissions that are not actively required.
2. Secret management, not secret storage. Secrets should never live in environment variable files, hardcoded in workflow YAML, or committed to source control β even in private repositories. Use a dedicated secret management system (HashiCorp Vault, AWS Secrets Manager, GitHub Actions secrets with OIDC, etc.) and rotate credentials on a defined schedule. Enable secret scanning in your repository host to catch accidental commits before they propagate.
3. Dependency pinning by digest, not by tag. Container image tags and package version tags are mutable β a tag can be overwritten to point to malicious content without any visible change in your pipeline configuration. Pin dependencies using immutable content digests (SHA-256 hashes) instead. For GitHub Actions specifically, pin actions to commit SHAs rather than version tags to prevent tag-hijacking attacks.
4. Branch protection and pull request gates. Require pull request reviews before any code can be merged to main or release branches. Require CI checks to pass before merge. Restrict who can push directly to protected branches. These controls prevent unauthorized code β including injected malicious code β from entering the delivery pipeline without review.
5. Software Composition Analysis (SCA) in the pipeline. Run dependency vulnerability scanning on every pull request and block merges on critical findings. Tools like OWASP Dependency-Check, Snyk, Trivy, or Grype can be integrated as pipeline steps and configured with fail thresholds. Update your dependency lockfiles regularly and treat high-severity dependency vulnerabilities with the same urgency as application bugs.
6. Container image scanning before deployment. Scan every container image for known vulnerabilities before it is pushed to your registry or deployed. Configure your registry (ECR, GCR, Docker Hub) to run automated scanning on push. Set policies that block images with critical CVEs from reaching production. Treat the base image as a dependency that needs regular updates.
7. SAST integration in the developer workflow. Static application security testing should run on every pull request, not just in a nightly batch job. Fast, incremental SAST (Semgrep, CodeQL, Bandit for Python, etc.) integrated into the PR workflow gives developers security feedback at the moment they can act on it most efficiently β before code is merged, not after it's in production.
8. Ephemeral, isolated build environments. Each pipeline job should run in a fresh, ephemeral environment that is destroyed after the job completes. Persistent runners accumulate state β cached credentials, leftover artifacts, modified toolchains β that attackers can exploit. Ephemeral runners (GitHub Actions hosted runners, ephemeral Docker containers, cloud-native build systems) eliminate this entire attack surface.
9. Audit logging and pipeline observability. Every pipeline execution should produce detailed audit logs: who triggered it, what code was built, which dependencies were resolved, what credentials were accessed, and what was deployed. These logs are essential for incident response when something goes wrong β and for compliance with frameworks like SOC 2 and FedRAMP that require demonstrable pipeline controls.
10. Build provenance and artifact signing. Implement SLSA provenance generation for your build artifacts. Sign artifacts using Sigstore/Cosign or similar tools. Verify signatures at deployment time. This creates a verifiable chain of custody from source commit to production deployment that makes supply chain tampering detectable.
Comparing Pipeline Security Approaches by Maturity Level
| Maturity Level | Key Controls | Typical Team Profile | SLSA Equivalent |
|---|---|---|---|
| Basic | Branch protection, secret scanning, CI gate | Early-stage startup, small team | SLSA 1 |
| Intermediate | + SCA scanning, image scanning, SAST, secret manager | Growth-stage, engineering team of 10β50 | SLSA 2 |
| Advanced | + Dependency digest pinning, ephemeral runners, audit logging, DAST | Enterprise or regulated industry | SLSA 3 |
| Hardened | + Hermetic builds, artifact signing, provenance attestation, policy enforcement at deploy | Critical infrastructure, government, financial | SLSA 4 |
The Organizational Dimension: Security as a Shared Pipeline Concern
Technical controls are necessary but not sufficient. The most common reason pipeline security controls fail in practice is not that the right tools are unavailable β it is that security is treated as a separate team's problem rather than a shared engineering responsibility. DevSecOps as a practice means that developers own the security posture of their pipelines the same way they own their build configuration.
Concretely, this means security scanning failures should break the build with the same authority as test failures. It means security findings in the pipeline surface in the developer's normal workflow β in their pull request, not in a separate security ticket queue that no one checks. It means the team has agreed on fail thresholds and exception processes before they are needed in a time-pressured situation. And it means pipeline security controls are reviewed in team retrospectives the same way performance regressions are.
Frequently Asked Questions
How do we secure secrets in GitHub Actions without a dedicated secrets manager?
GitHub Actions has built-in encrypted secrets storage that is sufficient for many teams. The critical additional step is using OIDC (OpenID Connect) token federation rather than long-lived static credentials for cloud provider access. With OIDC, your pipeline requests short-lived tokens at runtime that expire immediately after the job β meaning there is no static credential to steal. GitHub, AWS, GCP, and Azure all support OIDC federation natively. For sensitive production workloads, upgrading to a dedicated secrets manager like HashiCorp Vault or AWS Secrets Manager is worth the operational investment.
Does adding security scanning to the pipeline significantly slow down delivery?
Incremental, well-configured scanning adds seconds to minutes to pipeline runtime β not hours. The key is running scanning in parallel with other pipeline stages, configuring scan scopes appropriately (scanning only changed files in PRs, not the entire codebase on every commit), and right-sizing fail thresholds to critical and high severity only in the initial rollout. Teams that run all scanning in a single sequential gate at the end of the pipeline experience the most slowdown; teams that distribute scanning across pipeline stages as parallel checks see minimal impact on delivery speed.
What should we prioritize if we can only implement three controls right now?
If resources are constrained, implement these three in order: (1) secret scanning and proper secret management β exposed credentials are the most common pipeline attack entry point; (2) branch protection with required reviews and CI status checks β this closes the unauthorized code injection vector that makes supply chain attacks possible; (3) dependency vulnerability scanning on every PR β dependencies are the largest unexplored attack surface in most pipelines. These three controls address the majority of real-world CI/CD compromise scenarios and can typically be implemented in a single sprint without significant operational disruption.
Bottom Line: CI/CD pipeline security is not a luxury feature for large enterprises β it is table stakes for any team shipping software that touches production systems or customer data. We recommend starting with a pipeline security audit this week: inventory every secret, permission, and third-party dependency in your pipeline, then apply least privilege aggressively, pin your dependencies by digest, and enable secret scanning. From there, layer in SCA, container scanning, and SAST as parallel pipeline stages. The OWASP CI/CD Top 10 and the SLSA framework provide a proven roadmap; the only missing ingredient is making pipeline security a first-class engineering priority in your team.
Sources & References:
OWASP Top 10 CI/CD Security Risks (2022). Open Web Application Security Project.
SLSA Framework: Supply-chain Levels for Software Artifacts. Google / OpenSSF.
NIST Secure Software Development Framework (SSDF), SP 800-218.
Disclaimer: This article is for informational purposes only. Technology landscapes change rapidly; verify information with official sources before making technical decisions.