Cryptographic Attestation in CI/CD Pipelines
How to use cryptographic attestation to prevent supply chain attacks in CI/CD pipelines.
Cryptographic Attestation in CI/CD Pipelines
SolarWinds. XZ Utils. 3CX. Every major supply chain attack of the past five years shares a common thread: the malicious artifact passed through the build pipeline without triggering any alert, because no one was cryptographically verifying what came out of the pipeline — or what went in.
Cryptographic attestation is the technical answer to this problem. It is not optional — it has become a fundamental security requirement for any exposed CI/CD pipeline.
Anatomy of Supply Chain Attacks
SolarWinds (2020): attackers compromised the Orion build system and injected malicious code directly into the compilation process. The binary, signed with SolarWinds' legitimate certificate, distributed a backdoor to 18,000 organizations.
XZ Utils (2024): two years of social engineering to become maintainer of a critical library, then injection of a backdoor into the release process. The malicious code was in distribution artifacts but not in the versioned source code — deliberately bypassing reviews.
Common pattern: the attack targets the pipeline, not the code. Signing the final binary proves nothing about the integrity of the process that produced it.
SLSA: Supply-chain Levels for Software Artifacts
SLSA (pronounced "salsa") is a Google framework that defines progressive levels of supply chain security:
SLSA Build L1 — Provenance generated by the builder
SLSA Build L2 — Provenance signed by the hosted builder
SLSA Build L3 — Isolated build, verifiable parameters, verified sources
Note: SLSA v1.0 restructured the tracks. The legacy 0.x classification (Level 1 to 4) is still referenced in some tools and historical documentation; the current official Build track is L1–L3.
Provenance is the document describing how an artifact was produced: which source code, which builder, which parameters, at what time. Cryptographically signed, it allows post-hoc verification that the artifact matches what was expected.
Ed25519 Signatures and Sigstore
Ed25519 is the recommended signing algorithm for attestation: excellent performance, resistance to timing attacks, short keys (32 bytes).
The key problem: a signature is only as good as the protection of its private key. Storing keys in CI/CD secrets is an attack surface. Sigstore solves this with ephemeral signatures tied to OIDC identity.
# Full GitHub Actions example — keyless signing via OIDC
jobs:
sign:
permissions:
id-token: write # required to obtain the OIDC token
contents: read
steps:
- uses: sigstore/cosign-installer@v3
- name: Sign image
run: |
cosign sign --yes \
registry.alien6.io/app:v1.2.3@sha256:abc123...# Verify the image before deployment
cosign verify \
--certificate-identity="https://github.com/alien6-studio/app/.github/workflows/release.yml@refs/tags/v1.2.3" \
--certificate-oidc-issuer="https://token.actions.githubusercontent.com" \
registry.alien6.io/app:v1.2.3Attestations in GitHub Actions
# .github/workflows/release.yml
jobs:
attest:
permissions:
id-token: write # required for OIDC signing
attestations: write # required to write the attestation
contents: read
steps:
- name: Generate SLSA provenance attestation
uses: actions/attest-build-provenance@v2
with:
subject-name: registry.alien6.io/app
subject-digest: ${{ steps.build.outputs.digest }}
push-to-registry: true
# Note: push-to-registry pushes the attestation to the registry
# but is not sufficient — verify via cosign or gh attestation verify
- name: Sign image with Sigstore
run: |
cosign sign --yes \
registry.alien6.io/app@${{ steps.build.outputs.digest }}Integration at Deployment Time
Attestation only has value if it is verified before deployment. Policy enforcement happens at the Kubernetes admission controller level:
# Kyverno Policy: reject unsigned images
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-signed-images
spec:
rules:
- name: check-image-signature
match:
resources:
kinds: ['Pod']
verifyImages:
- imageReferences: ['registry.alien6.io/*']
attestors:
- entries:
- keyless:
issuer: 'https://token.actions.githubusercontent.com'
subject: 'https://github.com/alien6-studio/*'Implementation Recommendations
- Start with SLSA Level 2: signed provenance on all production artifacts. Achievable in a day with GitHub Actions.
- Adopt digest pinning (not tag pinning) in your deployment manifests —
image@sha256:...is immutable, a tag is not. - Audit your dependencies: the pipeline tools themselves (actions, orbs, buildpacks) are also attack vectors. Verify they are signed.
- Deploy an admission controller that rejects images without valid attestation — a signature on the registry means nothing if it is never verified.
Cryptographic attestation does not make attacks impossible. It dramatically improves verifiability, auditability, and tamper detection — making falsification computationally infeasible and pipeline compromises much harder to conceal.