devsecops5 min readCI/CD Pipeline Security: 15 Best Practices for Securing Your Software Delivery PipelineLearn 15 critical CI/CD pipeline security best practices including dependency scanning, artifact signing, SBOM generation, secret management, and incident response.ShieldOps Team2026-06-15 ·8Your CI/CD pipeline is the most valuable target an attacker can aim for. Compromise the pipeline, and you compromise every application it builds, every artifact it signs, and every deployment it pushes. This is not theoretical. Supply chain attacks that exploit CI/CD pipelines have increased by over 600% in the last three years, and each one started with a single unprotected pipeline configuration.Securing your CI/CD pipeline is no longer optional. It is the single highest-leverage security investment you can make, because the pipeline is the intersection of code, infrastructure, and access. A vulnerability in your pipeline is a vulnerability in every application running in production. In this guide, we cover fifteen CI/CD security best practices organized by pipeline stage, from source code to deployment.Why CI/CD Pipeline Security Deserves Its Own StrategyTraditional security models treat the CI/CD pipeline as a transparent transport layer. Code goes in, artifacts come out, and security stops at the endpoints. This assumption is dangerously wrong. The pipeline itself is a complex distributed system with its own attack surface: build agents that execute arbitrary code, cached dependencies that can be poisoned, secret stores that leak credentials, and artifact registries that distribute signed binaries.According to the 2025 Cloud-Native Security and Usage Report, 78% of organizations experienced at least one security incident related to their CI/CD pipeline in the past year. The most common causes were misconfigured access controls (34%), vulnerable pipeline dependencies (28%), and exposed credentials in build logs (22%). Every one of these is preventable with the right practices in place.Source Code and Dependency Security1. Scan Dependencies for Known Vulnerabilities Before Every BuildModern applications ship with hundreds of open-source dependencies. A single vulnerable library in your dependency tree can compromise your entire application. Integrate Software Composition Analysis (SCA) tools directly into your CI pipeline and fail the build on HIGH or CRITICAL vulnerabilities.# Example using Trivy in a CI step - name: Scan dependencies run: | trivy fs --exit-code 1 \ --severity HIGH,CRITICAL \ --scanners vuln \ ./ Pin your dependencies to specific versions. Lock files in npm (package-lock.json), pip (requirements.txt with hashes), and Go (go.sum) exist for exactly this reason. If you cannot reproduce a build exactly, you cannot audit it meaningfully.2. Prevent Secrets from Being Committed to Source ControlCredentials committed to Git are compromised. There is no such thing as a secret that was deleted from Git history, because Git preserves every commit. Use pre-commit hooks with tools like GitLeaks or TruffleHog to block secrets before they reach the remote repository.# .pre-commit-config.yaml repos: - repo: https://github.com/gitleaks/gitleaks rev: v8.18.0 hooks: - id: gitleaks For secrets that must exist at build time, use your CI platform's built-in secret store or integrate with a dedicated vault. Never store secrets in pipeline configuration files, environment variables in the UI, or in repository-level settings that are visible to all contributors.3. Sign Commits and TagsSigned commits authenticate that a specific developer authored a change. Without signing, anyone with commit access to the repository can impersonate any other contributor. Use GPG or SSH keys with your Git platform to sign every commit and tag, and enforce signing at the repository level.git config --global commit.gpgsign true git config --global tag.gpgsign true In GitHub, enable "Require signed commits" in branch protection rules. In GitLab, set the "Reject unsigned commits" option. This prevents unsigned code from entering protected branches where it could trigger pipeline execution.Build and Artifact Security4. Use Ephemeral, Isolated Build EnvironmentsEvery build should start from a clean environment. Shared build runners that persist state between builds can leak credentials, cache vulnerabilities, or deliver poisoned artifacts from a previous compromised run. Use containerized build agents that are destroyed after every job.# GitHub Actions uses ephemeral runners by default # For self-hosted, ensure cleanup on job completion runs-on: ubuntu-latest container: image: node:18-alpine If you use self-hosted runners, deploy them as ephemeral containers that are destroyed and recreated after each job. Never reuse a runner across different projects or trust levels without full cleanup in between.5. Generate and Sign SBOMs for Every ArtifactA Software Bill of Materials (SBOM) is a complete inventory of all components in your application. It is required for compliance withNIST SP 800-190and Executive Order 14028. Generate an SBOM during every build and sign it to prevent tampering.# Generate SBOM with Syft syft packages ./app -o spdx-json > sbom.spdx.json # Sign with Cosign cosign sign-blob --key cosign.key sbom.spdx.json > sbom.sig Store the signed SBOM alongside the artifact in your registry. When an incident occurs, the SBOM tells you exactly which components are affected, eliminating the need to reverse-engineer a deployed artifact.6. Scan Container Images for Vulnerabilities at Build TimeContainer images are the most common deployment artifact, and they accumulate vulnerabilities from base images, installed packages, and application dependencies. Scan every image immediately after building it and before pushing it to the registry.# Build and scan in one pipeline step docker build -t myapp:${{ github.sha }} . trivy image --exit-code 1 --severity HIGH,CRITICAL myapp:${{ github.sha }} docker push myapp:${{ github.sha }} If the scan fails, the image should not be pushed. Enforce this at the registry level as well: configure your container registry to reject images that fail vulnerability scanning, even if the CI pipeline pushes them.7. Sign and Verify Artifacts Before DeploymentCode signing is not just for mobile apps. Every artifact you deploy should be digitally signed, and the deployment target should verify the signature before accepting it. This prevents a compromised registry from distributing tampered artifacts to your production environment.# Sign container image with Cosign cosign sign --key cosign.key myapp:${{ github.sha }} # Verify before deployment cosign verify --key cosign.pub myapp:${{ github.sha }} In Kubernetes, use admission controllers likeKyvernoor OPA/Gatekeeper to enforce signature verification at deploy time. If the image is not correctly signed, the pod is not created.Pipeline Configuration and Access Control8. Apply Least Privilege to Pipeline Service AccountsCI/CD service accounts often have broad permissions because nobody wants to debug a "permission denied" failure at 3 AM. But a pipeline token with write access to your production namespace is a catastrophic security gap if the pipeline is compromised. Apply the exact same RBAC principles you use for production workloads to your pipeline identities.Segment pipeline access by environment: a CI job building a development branch should not have access to production secrets. Use OpenID Connect (OIDC) tokens for cloud provider access instead of long-lived access keys.# GitHub Actions OIDC with AWS - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: arn:aws:iam::123456:role/CI-Role aws-region: us-east-1 When the pipeline runs, it requests a short-lived token scoped to the specific job. No long-lived keys to store or rotate, and access is automatically revoked when the job completes.9. Restrict Pipeline Trigger ConditionsNot every commit should trigger a full production pipeline. An attacker who pushes a tag to a forked repository should not be able to trigger your production deployment workflow. Use explicit trigger conditions that limit pipeline execution to trusted events.# Only run deployment on main branch push on: push: branches: - main tags: - 'v*' For pull requests from forks, ensure that secrets are not available to the pipeline. GitHub Actions does this by default, but verify similar settings in your CI platform.10. Separate Build, Test, and Deploy Stages with Different CredentialsA single pipeline with one set of credentials that covers build, test, and deploy means that a vulnerability in the build step compromises the entire deployment chain. Break your pipeline into stages with distinct credentials scoped to exactly what each stage needs.The build stage has access to source code and dependency registries. The test stage has access to staging databases and API endpoints. The deploy stage has access to production infrastructure. If the build stage is compromised, the attacker cannot access production because the deploy credentials were never available during the build phase.Secret Management in CI/CD11. Never Hardcode Secrets in Pipeline DefinitionsPipeline definition files — just like any other code — should never contain hardcoded secrets. A data source URL, an API token, or a deployment password stored in a pipeline YAML file is visible to everyone with access to the repository and any CI platform administrator.Use your CI platform's built-in secret management features. Map secrets from the platform's secure store into environment variables or files at runtime, and restrict which branches and environments can access each secret.12. Use Short-Lived Credentials Over Static API KeysLong-lived API keys that are stored in CI/CD systems are one of the most common sources of credential leaks. If a static key is exposed through a build log, a debug output, or a compromised artifact, it remains valid until someone manually rotates it. Short-lived credentials limit the damage window.Use OIDC-based authentication for cloud access (AWS, GCP, Azure) and dynamic secrets via HashiCorp Vault or cloud secret managers. These credentials expire after the job completes and cannot be reused.13. Audit Secret Access in PipelinesYou should know exactly which pipeline jobs accessed which secrets and when. Most CI platforms log secret access, but these logs are rarely reviewed. Set up automated monitoring that alerts on unusual secret access patterns, such as a secret being accessed by a pipeline run triggered from a new branch or contributor.For particularly sensitive secrets, require manual approval before they can be used in a pipeline run. This adds friction, but for production deployment keys, that friction is justified.Monitoring and Incident Response14. Collect and Monitor Pipeline Audit LogsWhen an incident occurs, your pipeline logs are the forensic evidence you need to understand what happened. Forward CI/CD audit logs to your SIEM or centralized logging platform. Monitor for anomalous events: pipeline runs triggered at unusual times, configuration changes to pipeline definitions, and new secrets being added or modified.Set up alerts for:Unauthorized changes to pipeline configuration filesSecrets accessed outside of normal working hoursBuilds that download unexpected dependencies or executablesDeployments from unrecognized contributors or branches15. Have a Pipeline Incident Response PlanA compromised CI/CD pipeline requires immediate, coordinated action. Unlike a server breach, you cannot simply take the pipeline offline and investigate — your entire software delivery depends on it. Create a dedicated incident response plan for pipeline compromises that includes:Immediate revocation of all pipeline credentialsAudit of all artifacts produced since the compromise windowRotation of all secrets that passed through the pipelineReview of all deployments made during the compromised periodPost-mortem with specific technical controls to prevent recurrenceCI/CD Pipeline Security Checklist⬜ Dependencies are scanned for vulnerabilities before every build⬜ Secrets are blocked from being committed via pre-commit hooks⬜ All commits and tags are signed⬜ Build environments are ephemeral and isolated⬜ SBOM is generated and signed for every artifact⬜ Container images are scanned and signed before push⬜ Pipeline service accounts have least-privilege permissions⬜ Pipeline triggers are restricted to trusted events⬜ Build, test, and deploy stages use separate credentials⬜ No secrets are hardcoded in pipeline definitions⬜ Long-lived API keys are replaced with OIDC or dynamic secrets⬜ Secret access is audited and monitored⬜ Pipeline audit logs are forwarded to SIEM⬜ Incident response plan for pipeline compromises exists⬜ Runtime monitoring detects anomalous build behaviorFrequently Asked QuestionsWhat is the biggest risk to CI/CD pipelines?Credential exposure. A single exposed CI/CD token can give an attacker access to your entire software supply chain. This is followed closely by vulnerable dependencies that enter the pipeline through unverified third-party actions or plugins.Should I use third-party CI/CD actions and plugins?Use them with caution. Third-party actions execute arbitrary code in your pipeline context. Pin them to specific versions (not version ranges or latest), audit the source code of critical actions, and restrict which actions are allowed in your organization.How do I secure a multi-tenant CI/CD environment?Use separate runner pools for different trust levels. Ephemeral runners for each job prevent cross-tenant contamination. Never mount Docker sockets inside CI runners that serve multiple teams. Apply network policies to isolate build environments from production.What is the difference between SAST, DAST, and SCA?SAST (Static Application Security Testing) analyzes source code without executing it. DAST (Dynamic Application Security Testing) tests running applications. SCA (Software Composition Analysis) scans open-source dependencies and their licenses. All three should be integrated into your pipeline for comprehensive coverage.How often should I rotate CI/CD credentials?Static credentials (service account tokens, API keys) should be rotated every 90 days minimum. For OIDC-based and dynamic secrets, the platform handles rotation automatically. Any credential involved in a security incident must be rotated immediately.ConclusionCI/CD pipeline security is not a single tool or a one-time configuration. It is a practice that spans your entire software delivery lifecycle, from the moment a developer commits code to the moment an artifact runs in production. The fifteen practices in this guide form a complete security framework for your pipeline, but you do not need to implement all of them at once.Start with the highest-impact changes: scan dependencies before every build, block secrets from reaching your repository, and use short-lived credentials for pipeline access. Then add artifact signing, SBOM generation, and audit logging. Finally, build the incident response plan that prepares you for the compromise every team eventually faces.Your pipeline is the most critical piece of infrastructure you manage. Treat it that way.Ready to apply these concepts?Generate a Software Bill of Materials and support your compliance workflow.Generate Your SBOMRelated PostsTrivy vs Docker Scout vs Snyk: Comparing Container Vulnerability Scanners in 20262026-06-15Shift Dockerfile Security Left: End‑to‑End SBOM Generation in CI/CD2026-05-26Your takeRate this article or leave a commentShare Submit commentHave more questions? Check ourFAQ