CI/CD Pipeline Security Controls Buyers Should Request
CI/CD security is source-to-artifact integrity work. Review starts with one question: can an unapproved person, workflow, runner, dependency, or secret change what reaches a release target? A pipeline that builds successfully is not evidence that release inputs were protected. SLSA describes provenance as verifiable information about where, when, and how artifacts were produced; consumers still need a policy that decides what evidence they accept. NIST SSDF frames secure software work as practices integrated into development, not a one-time scan.
This guide creates a completed review artifact. It does not certify a pipeline, prove software is safe, or promise a release outcome. Scope must name repositories, CI providers, runners, artifact registries, deployment paths, and identities examined.
Start with release path map
Draw one path from merge to production: protected branch, workflow file, runner, build inputs, artifact registry, approval point, deployment identity, and target. Mark every actor that can edit or invoke each step. Include reusable workflows, marketplace actions, package registries, build caches, and scripts fetched at runtime. These are execution inputs, not background details.
Example flow:
protected main commit
| reviewed workflow at commit
| isolated build runner with OIDC identity
| artifact digest plus provenance attestation
| policy verifies signer, builder, source commit, digest
| deploy job receives environment-scoped credential
| production accepts immutable digest
Protect workflow as privileged code
Treat changes to .github/workflows, CI configuration, deployment manifests, shared pipeline libraries, and permissions as privileged changes. Require protected-branch review. Restrict changes to environment protections, runner groups, and identity trust rules; test boundaries, not only settings.
Test unapproved workflow change, production deployment from pull request, secret from untrusted branch, altered action, and replayed approval. Record expected deny evidence with synthetic values in controlled non-production targets.
Separate build, test, publish, and deploy. Pull-request jobs get read-only repository access and no production secrets. Release job publishes only after policy checks. Deployment identity stays separate.
Review runner identity and isolation
Runner identity answers what workload is acting, for whom, and for how long. Prefer workload or federation tokens issued for a specific job and audience over long-lived cloud keys stored in CI. Bind trust rules to repository, branch or tag, workflow, environment, and intended audience where supported. Inspect token claims and cloud role conditions, then test a token from a different repository, branch, workflow, or audience. Each should fail.
Self-hosted runners need extra evidence. Capture runner inventory, ownership, network placement, patch level, image source, registration permissions, persistent workspace behavior, and which repositories can select each runner label. A shared persistent runner can retain source, credentials, caches, or artifacts between jobs. Prefer ephemeral isolated runners for untrusted or cross-repository work. If persistence remains, document cleanup verification and residual risk.
Keep secrets behind job boundaries
Secrets are capabilities, not configuration text. Inventory each secret: purpose, issuer, owner, consumers, environment, rotation path, expiry, and revocation method. A job gets only secret needed for its step and only in its approved context. Never pass production credentials to forked pull requests, unreviewed code, logs, artifacts, caches, or debug shells.
Configuration example:
permissions:
contents: read
id-token: write
jobs:
deploy:
if: github.ref == 'refs/heads/main'
environment: production
This is a starting boundary, not a complete control. Review environment approval rules, OIDC trust conditions, token lifetime, log masking, shell tracing, artifact upload rules, and whether child processes inherit credentials. Test that a build job cannot assume deploy role and deploy job cannot read unrelated secret.
Verify provenance before promotion
Provenance should connect artifact digest to expected source, dependencies, build process, and builder. SLSA provenance includes a build definition and run details such as builder identity and invocation metadata. Verification must check accepted signer-builder pair, source repository, immutable revision, workflow or build type, artifact digest, and required dependencies. Storing an attestation without checking it is not promotion control.
Example promotion decision: allow sha256:... only when attestation signer and builder match approved policy, resolved source commit equals release commit, workflow is approved, and artifact subject digest equals registry digest. Deny unknown builder, unexpected source, missing attestation, or mismatched digest. Preserve verifier output and attestation reference with release record.
Completed review artifact
| Release boundary | Evidence preserved | Accountable role | Decision | Corrective action |
|---|---|---|---|---|
| Workflow protection | branch rule export, review history, denied test | engineering owner | Pass/Fail | named file, approval gap, due date |
| Runner identity | token claims, trust policy, cross-context deny test | platform owner | Pass/Fail | runner scope reduction |
| Secret boundary | secret inventory, job permissions, log review | secret owner | Pass/Fail | revoke, rotate, split role |
| Provenance gate | attestation, verifier output, digest match | release owner | Pass/Fail | block promotion, add verifier |
| Deployment separation | environment rule, role policy, denied build-to-prod test | deployment owner | Pass/Fail | separate identities |
Keep configuration revision, job URL or run ID, policy export, test timestamp, and redacted output. Pass applies only to stated scope; failures need impact, owner, target date, and retest condition. Exceptions need approver, expiry, compensating control, and remediation.
What buyers should ask for
Ask for release-path diagram, workflow-change review rules, runner inventory, identity trust policy, secret inventory, provenance sample, verifier output, and exception register. Ask which events are logged and how a release can be reconstructed from source commit to deployed digest. Evidence should reveal boundaries without disclosing credentials or internal target data.
A sound review ends with a decision record: scope, artifacts examined, tests performed, pass/fail controls, exceptions, remediation owners, and retest triggers. That record makes pipeline security repeatable when workflow, runner fleet, or deployment design changes.
Make release evidence reproducible
A release record needs immutable references, not screenshots of a green job. Store commit SHA, workflow file SHA, runner image digest, artifact digest, attestation URI, verifier command and policy revision. Re-run verification from the retained artifact and compare resulting digest to deployment inventory. If a runner, action, or policy changes after release, preserve prior revision so reviewer can reconstruct decision without assuming current configuration existed then.