Skip to main content
← ArticlesLire en français
15 February 2026·Alien6 Research

Cryptographic Attestation in CI/CD Pipelines

How to use cryptographic attestation to prevent supply chain attacks in CI/CD pipelines.

DevSecOpsSécuritéCI/CD

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.3

Attestations 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

  1. Start with SLSA Level 2: signed provenance on all production artifacts. Achievable in a day with GitHub Actions.
  2. Adopt digest pinning (not tag pinning) in your deployment manifests — image@sha256:... is immutable, a tag is not.
  3. Audit your dependencies: the pipeline tools themselves (actions, orbs, buildpacks) are also attack vectors. Verify they are signed.
  4. 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.