How to Secure a CI/CD Pipeline: A Prioritized Checklist
A prioritized, practical checklist for securing CI/CD pipelines: access control, secrets, runner isolation, dependency and action pinning, artifact signing and logging.
Secure a CI/CD pipeline in priority order. First, lock down who can change code and pipeline files. Second, remove long-lived secrets and use short-lived credentials such as OIDC. Third, pin and scan third-party actions and dependencies. Fourth, isolate runners and give jobs least-privilege tokens. Finally, sign build artifacts and log everything, so tampering is blocked or quickly detected.
Photo: Unsplash
On this page
- Why CI/CD pipelines are high-value targets
- Priority 1: Control who can change code and pipelines
- Priority 2: Get secrets out of the pipeline
- Priority 3: Pin and verify third-party actions and dependencies
- Priority 4: Isolate runners and limit job permissions
- Priority 5: Build security checks into the pipeline
- Priority 6: Sign artifacts and log everything
- Where to start this week
- The bottom line
- Sources
Your CI/CD pipeline has more power than almost anyone on your team. It can read your source code, hold your cloud credentials, publish packages and deploy straight to production. That makes it one of the most attractive targets an attacker can find.
Real attacks prove it. In March 2025, the widely used tj-actions/changed-files GitHub Action was compromised, and CISA warned that it could expose secrets such as access keys, personal access tokens, npm tokens and private RSA keys in workflow logs. Teams that used it had to audit their pipelines and rotate credentials in a hurry.
The good news: most pipeline risk comes from a handful of fixable problems. This guide gives you a prioritized list, starting with the changes that block the most attacks for the least effort.
Why CI/CD pipelines are high-value targets
A pipeline sits at the center of your software supply chain. If an attacker controls it, they can:
- Steal secrets and move into your cloud accounts
- Inject malicious code into builds that you then ship to customers
- Publish poisoned packages under your name
- Deploy changes to production that bypass code review
NSA and CISA published joint guidance in June 2023, Defending Continuous Integration/Continuous Delivery (CI/CD) Environments, describing these environments as attractive targets for malicious actors. NIST followed in February 2024 with SP 800-204D, which covers how to build software supply chain security into DevSecOps CI/CD pipelines.
If you’re new to the concepts, start with what CI/CD is and what a software supply chain attack is.
The main risks, according to OWASP
The OWASP Top 10 CI/CD Security Risks is a helpful map of what goes wrong:
| ID | Risk | What it looks like in practice |
|---|---|---|
| CICD-SEC-1 | Insufficient flow control mechanisms | Someone can push to main or deploy without review |
| CICD-SEC-2 | Inadequate identity and access management | Stale accounts, shared logins, overly broad permissions |
| CICD-SEC-3 | Dependency chain abuse | Malicious or typosquatted packages pulled into builds |
| CICD-SEC-4 | Poisoned pipeline execution | Attacker edits pipeline config or build scripts through a pull request |
| CICD-SEC-5 | Insufficient pipeline-based access controls | Every job can reach every secret and system |
| CICD-SEC-6 | Insufficient credential hygiene | Long-lived tokens, secrets in code or logs |
| CICD-SEC-7 | Insecure system configuration | Unpatched CI servers, default settings |
| CICD-SEC-8 | Ungoverned usage of third-party services | Unknown integrations and apps with access to repositories |
| CICD-SEC-9 | Improper artifact integrity validation | Unsigned builds that could be swapped or altered |
| CICD-SEC-10 | Insufficient logging and visibility | No way to detect or investigate tampering |
The checklist below addresses all 10, in the order most teams should tackle them.
Key takeaway: Treat your pipeline like production infrastructure, because it can change production. Start with access control and secrets; they block the most damaging attacks.
Priority 1: Control who can change code and pipelines
If an attacker can change your pipeline definition, every other control can be bypassed.
- Protect main and release branches. Require pull requests, at least 1 approving review and passing status checks before merge. Block force pushes.
- Protect pipeline files. Require review from a designated owner (for example, with a CODEOWNERS file) for changes to workflow files, build scripts and deployment configs.
- Require multi-factor authentication for everyone with access to your source control and CI system. Phishing-resistant methods such as passkeys or security keys are best.
- Use least privilege for people. Few people need admin rights to repositories or CI settings. Review access quarterly and remove leavers promptly.
- Separate deploy approval from code authorship for production, using protected environments with required reviewers.
NIST SP 800-204D recommends treating write access to source code management as high risk and tightly controlling it.
Priority 2: Get secrets out of the pipeline
Stolen credentials are the most common payoff from a pipeline compromise. Reduce how many exist, how long they last and who can reach them.
- Replace long-lived cloud keys with OpenID Connect (OIDC). GitHub’s security hardening guide recommends OIDC so workflows can authenticate directly to supported cloud providers without storing long-lived secrets. GitLab and other CI systems offer similar options.
- Store remaining secrets in a secrets manager or your CI platform’s encrypted secret store, never in code, pipeline files or container images.
- Scope secrets narrowly. Give each environment and job only the secrets it needs. Production deploy credentials should only be available to the production deploy job.
- Keep secrets out of logs. GitHub advises against storing structured data such as JSON or YAML as a single secret, because log redaction relies on exact matches, and recommends registering derived values (such as encoded tokens) as secrets too.
- Scan for leaked secrets in repositories and pull requests, and rotate anything that leaks immediately.
- Rotate on a schedule and after any incident, including third-party compromises like the 2025 GitHub Action incident.
Priority 3: Pin and verify third-party actions and dependencies
Your pipeline runs other people’s code: CI plugins, actions, base images and package dependencies. Each one is a potential entry point.
- Pin third-party actions to a full-length commit SHA. GitHub recommends this because tags can be moved or deleted, which is how compromised tags can silently change what you run. Where your platform supports dependency lockfiles for workflows, use them.
- Audit actions before adopting them, and prefer actions from verified creators or your own organization.
- Use lockfiles for application dependencies and install from them in CI, so builds don’t silently pick up new versions.
- Run software composition analysis (SCA) to flag known vulnerable or malicious packages on every build. NIST SP 800-204D calls for detecting open-source dependencies with appropriate SCA tools.
- Use trusted base images, pin them by digest and rebuild regularly to pick up patches.
- Watch for typosquatting and dependency confusion by using private registries with scoped package names for internal libraries.
For broader coding practices, see our secure coding best practices.
Priority 4: Isolate runners and limit job permissions
A runner is the machine that executes your jobs. If one job can poison a runner, the next job (and its secrets) may be exposed.
- Prefer ephemeral runners that start fresh for each job and are destroyed afterward.
- Don’t use self-hosted runners with public repositories. GitHub’s guidance says they should almost never be used for public repos, because anyone can open a pull request that runs code on them.
- Separate runner pools by trust level. Untrusted pull request builds should never share runners with production deployments.
- Restrict network access from runners to what builds actually need.
- Set least-privilege job tokens. In GitHub Actions, default the
GITHUB_TOKENto read-only and grant extra permissions per job only when needed. - Be careful with privileged triggers. GitHub warns that
pull_request_targetandworkflow_runrun with elevated privileges; never check out and run untrusted pull request code in them. - Prevent script injection. Don’t paste untrusted input, such as pull request titles or branch names, directly into shell commands. Pass it through environment variables instead.
Compare how platforms handle these controls in our GitHub Actions vs GitLab CI vs Jenkins guide.
Priority 5: Build security checks into the pipeline
Once the pipeline itself is safer, use it to catch problems in your code:
- Static application security testing (SAST) for common coding flaws
- Secret scanning on every push
- Dependency and container image scanning
- Infrastructure as code scanning for misconfigured cloud resources; see what infrastructure as code is
- Dynamic testing (DAST) against staging for web apps
Tune tools so they block on high-severity, high-confidence findings and report the rest. Pipelines that fail on noise get bypassed. Our guide to DevSecOps explains how to roll this out without slowing teams down.
Priority 6: Sign artifacts and log everything
The final layer proves that what you deploy is what you built, and lets you investigate when something goes wrong.
- Generate build provenance. The SLSA framework describes build levels: Build L1 means provenance exists, L2 means a hosted build platform generates and signs it, and L3 adds hardened, isolated builds that keep signing secrets away from user-defined build steps.
- Sign artifacts and container images, and verify signatures before deployment.
- Produce a software bill of materials (SBOM) so you know what’s inside each release.
- Centralize CI/CD logs (who changed what, which jobs ran, which secrets were accessed) and send them to your security monitoring.
- Alert on unusual activity, such as pipeline file changes outside normal review, new admin users or jobs running at odd times.
- Include the pipeline in your incident response plan. Know how you would revoke tokens, pause deployments and rebuild runners. Our incident response plan guide can help.
Where to start this week
If you can only do a few things, do these in order:
- Turn on branch protection with required reviews for main and for pipeline files.
- Enforce MFA for source control and CI accounts.
- Set default job tokens to read-only.
- Move 1 cloud deployment to OIDC and delete its long-lived keys.
- Pin third-party actions to commit SHAs and enable dependency scanning.
- Turn on secret scanning and rotate anything it finds.
- Schedule a quarterly access review of repositories, CI settings and integrations.
These steps align with the zero trust idea of never trusting by default; see zero trust security explained and our cloud security checklist for the bigger picture.
The bottom line
CI/CD pipelines hold the keys to your code, cloud and customers, so they deserve the same protection as production. Start with who can change code and pipelines, then eliminate long-lived secrets, pin and scan what you pull in, isolate runners and narrow job permissions. Finish with signed artifacts and good logging. Each step is manageable on its own, and together they make a pipeline compromise far harder and far easier to spot.
Sources
- OWASP Top 10 CI/CD Security Risks — the 10 CI/CD risk categories
- GitHub Docs: Security hardening for GitHub Actions — SHA pinning, GITHUB_TOKEN permissions, OIDC, secrets handling, self-hosted runners, privileged triggers
- NIST SP 800-204D: Strategies for the Integration of Software Supply Chain Security in DevSecOps CI/CD Pipelines — SCM access control and dependency analysis guidance
- CISA and NSA: Defending CI/CD Environments — joint guidance on CI/CD threats and mitigations
- CISA: Supply chain compromise of tj-actions/changed-files (CVE-2025-30066) — 2025 GitHub Action compromise and response steps
- SLSA v1.2: Build track basics — build provenance levels
Frequently asked questions
What is CI/CD security?
CI/CD security is the practice of protecting the systems that build, test and deploy your software, including source control, pipeline definitions, runners, secrets and artifacts. It also covers using the pipeline to run security checks on your code. Because pipelines can change production and hold powerful credentials, attackers target them to steal secrets or inject malicious code.
What is the biggest security risk in a CI/CD pipeline?
Exposed or overly powerful credentials are usually the most damaging risk, because a stolen deploy key or cloud token gives attackers direct access to production. Close behind is poisoned pipeline execution, where an attacker changes pipeline files or scripts through a pull request. Branch protection, short-lived credentials via OIDC and least-privilege job tokens address both.
How do I store secrets securely in CI/CD?
Use short-lived credentials such as OpenID Connect wherever your cloud provider supports it, so there is no long-lived secret to steal. Keep any remaining secrets in a secrets manager or your CI platform's encrypted store, scope them to specific jobs and environments, keep them out of logs, scan for leaks and rotate them regularly and after any incident.
Should I pin GitHub Actions to a commit SHA?
Yes, for third-party actions. GitHub's security guidance recommends pinning to a full-length commit SHA, because tags can be moved or deleted and may end up pointing to malicious code. The 2025 compromise of the tj-actions/changed-files action showed how a changed tag can affect every pipeline that references it. Use automated tools to keep pinned versions up to date.
Are self-hosted runners safe?
Self-hosted runners can be safe for private repositories if they are ephemeral, isolated by trust level and network-restricted. They are risky for public repositories, and GitHub says they should almost never be used there, because anyone can open a pull request that runs code on the runner. Hosted, ephemeral runners are simpler to secure for most teams.
What is SLSA in CI/CD?
SLSA (Supply-chain Levels for Software Artifacts) is a framework for proving how software was built. Its build levels range from Build L1, where provenance exists, to Build L3, where builds run on a hardened, isolated platform that keeps signing secrets away from build steps. It helps teams show that a deployed artifact came from a trusted build of reviewed code.
Is DevSecOps the same as CI/CD security?
Not exactly. DevSecOps is the broader practice of building security into every stage of software development, including design, coding, testing and operations. CI/CD security is one part of it, focused on protecting the pipeline itself and using it to run automated security checks. Most DevSecOps programs start by securing and instrumenting the pipeline.
Was this guide useful
No reviews yet. Share your experience and help other readers.