Securing Software Delivery: Zero Trust CI/CD Patterns for Modern Pipelines
Zero Trust CI/CD secures every pipeline action by verifying identity, intent, and execution environment before issuing short-lived, policy-approved access.
Join the DZone community and get the full member experience.
Join For FreeModern CI/CD pipelines are essential for rapid and reliable software delivery. But as pipelines automate more stages of the development lifecycle—from code validation to production deployment—they have also become a major target for exploitation.
Traditional pipelines often operate on broad trust: long-lived credentials, shared secrets, unverified execution environments, and permissive access controls. These assumptions introduce significant risks in today’s cloud-native infrastructure, where build agents may be ephemeral, distributed across regions, and provisioned dynamically.
Zero Trust CI/CD addresses these risks through a layered, defense-in-depth approach. It ensures that nothing in the pipeline is implicitly trusted—not the tasks being executed, not the identities invoking them, and not the systems executing those tasks. Every request—whether to build, test, deploy, or access infrastructure—must be evaluated dynamically based on verified identity, intent, context, and execution environment.
This model helps reduce attack surface, contain blast radius, and enforce policy-based controls without slowing down delivery workflows.
Establishing Identity in the Pipeline
A core Zero Trust principle is eliminating static credentials. Long-lived secrets are difficult to rotate, easy to misuse, and often stored in insecure ways. Most modern CI systems support OpenID Connect (OIDC), which enables jobs to request short-lived, signed identity tokens at runtime.
Example: OIDC Token Payload
{ "sub": "repo:org/shipping-service:ref:refs/heads/main", "aud": "sts.example.com", "job": "deploy", "env": "prod", "exp": 1713861000 }
These tokens can be verified to confirm what is running, who triggered it, and from which source. They allow access decisions to be made based on current job attributes rather than static assumptions.
Workload Identity and Execution Environment Verification
Beyond the pipeline job itself, what runs the pipeline matters. Agents and runners that execute CI/CD tasks must also be identified and verified. Without this layer, an attacker could impersonate a legitimate job by hijacking the runner or execution node.
SPIFFE (Secure Production Identity Framework for Everyone) and SPIRE provide a standardised, cryptographic workload identity standard/framework. It issues short-lived, automatically rotated credentials that workloads use to prove who they are—without any embedded secrets.
SPIFFE identities:
- Are issued automatically based on workload attributes
- Rotate frequently and expire quickly
- Can be verified using mutual TLS or JWTs
- Extend Zero Trust to the infrastructure running pipeline jobs, not just the jobs themselves
This allows the CI/CD system to ensure not only that the workload is authorized, but also that the environment executing it is properly attested. In some implementations, a policy-based credential issuance service is used to exchange identity and attestation claims for scoped, short-lived credentials—without exposing long-term secrets.
As explored in a recent research arXiv:2504.14760, workload identity is a foundational requirement for modern Zero Trust infrastructure, enabling end-to-end attestation of both tasks and their execution environments.
Enforcing Policy With Rego
Identity alone is not enough. Zero Trust pipelines must also enforce whether an action should occur under the given conditions. This is where policy-as-code becomes critical.
Using Rego with Open Policy Agent (OPA), access decisions can incorporate runtime signals like branch, commit signature, environment, time window, and infrastructure identity.
Example: Deployment Approval Policy
allow { input.identity.role == "ci-cd-pipeline" input.context.branch == "main" input.context.commit_signed == true input.context.environment == "production" input.context.time >= "09:00" input.context.time <= "17:00" }
This policy allows deployments only from trusted sources, during approved hours, and with verified commits. Policies like these form the second line in a defense-in-depth model, reinforcing security even when identity is valid.
End-to-End Zero Trust CI/CD Flow
[ CI Job Triggered ] ↓ [ OIDC or SPIFFE Identity Issued ] ↓ [ Execution Environment Verified ] ↓ [ Policy Evaluated (OPA + Rego) ] ↓ [ Access Approved → Scoped Credential Issued ] ↓ [ Deployment or Resource Access Allowed ]
This flow ensures that who is requesting, what is being done, where it's running, and under what conditions are all verified before access is granted.
Rego Policy Examples for Context-Aware Access
Critical Service Deployments Requiring Ticket Approval
allow { input.context.service == "critical" input.context.ticket_approved == true input.identity.role == "ci-cd-pipeline" }
Tenant Isolation for Multi-Project Platforms
allow { input.identity.tenant == input.resource.tenant }
Runner Trust Enforcement (Infrastructure Verification)
allow { input.runner.id in ["trusted-runner-1", "trusted-runner-2"] input.runner.region == "us-west-2" }
These rules demonstrate how policy can integrate both workload-level and infrastructure-level trust boundaries.
Implementation Strategy: Four Phases
Zero Trust CI/CD can be implemented in a phased manner:
- Inventory pipeline access paths
Identify external services, secrets managers, cloud APIs, and internal resources. - Enable OIDC and SPIFFE
Use OIDC for CI jobs and SPIFFE to issue identity for build agents and runtime workloads. - Add Rego-based policy enforcement
Evaluate conditions at build, deploy, and runtime. Store policies in version control. - Issue access only after successful policy checks
Use short-lived tokens that expire quickly and are scoped to the specific task.
Developer-Friendly Security Controls
Zero Trust CI/CD doesn’t slow developers—it provides consistent guardrails. Policies can enable temporary access, enforce justifications, or gate sensitive actions.
Temporary Debug Access with Time-Limited Scope
regoallow { input.identity.on_call == true input.context.requested_ttl <= 30 input.context.purpose == "debug" }
High-Risk Deployments Requiring Annotations
regoallow { input.context.action == "deploy_hotfix" input.context.annotation != null contains(input.context.annotation, "approved by ticket") }
These safeguards align with operational practices while supporting velocity and autonomy.
Conclusion
Zero Trust CI/CD provides a scalable, evidence-driven approach to securing modern software delivery pipelines. It eliminates static trust assumptions by enforcing verifiable identity, runtime context checks, and infrastructure-level verification.
This model follows the principles of defense in depth, aligning with NIST and DoD guidance on Zero Trust architecture. By enforcing policy at every layer—who triggered the job, what code is running, where it is running, and under what conditions—organizations can reduce exposure, improve accountability, and support secure automation at scale.
Key practices include:
- Short-lived identity tokens using OIDC and SPIFFE
- Policy enforcement with Rego and Open Policy Agent
- Scoped, time-bound access with runtime context
- Execution environment verification for build agents and runners
- Credential issuance gated by intent, context, identity and workload attestation
These foundations enable CI/CD systems to move quickly while maintaining trust, control, and security throughout the delivery lifecycle.
Opinions expressed by DZone contributors are their own.
Comments