
Table of Contents
By Khimananda Oli | Last reviewed: September 2026
Supply chain attacks no longer target just your application code; they target the build process itself. Implementing SLSA Provenance: Hardening Your CI/CD Supply Chain Step by Step is the definitive defense against artifact tampering and compromised dependencies in 2026. While many teams generate Software Bills of Materials (SBOMs), few actually cryptographically bind that metadata to the build environment, leaving a critical trust gap. This guide moves beyond theory to show you exactly how to configure, sign, and verify provenance in production pipelines.
slsa-verifier CLI tool.What is SLSA Provenance and why does it matter for supply chain security?
SLSA (Supply-chain Levels for Software Artifacts) Provenance is not merely a log file; it is a verifiable statement of fact about your build. In my work auditing SOC 2 compliance for fintech clients, I frequently find that while teams have logs, they lack integrity. A standard CI log can be modified by anyone with write access to the storage backend. SLSA Provenance solves this by separating the generation of metadata from the signing of metadata, ensuring that even if a developer account is compromised, the build record remains immutable.
The core value lies in the "non-falsifiable" requirement of SLSA Level 3. The build service generates the provenance directly, and the user-controlled build script cannot influence its contents. This prevents attackers from injecting malicious code and then forging a clean build record to cover their tracks. For teams managing critical infrastructure or handling sensitive data, this distinction between "logged" and "attested" is the difference between passing an audit and surviving a breach.
If you are new to securing pipeline secrets as part of this hardening process, review handling secrets in CI/CD pipelines safely before implementing provenance, as key management is foundational to trust.
How do you generate SLSA provenance in GitHub Actions?
GitHub Actions is currently the most mature ecosystem for SLSA Level 3 provenance because of its OIDC integration with Sigstore Fulcio. You should never write your own provenance generator; instead, use the official reusable workflows provided by the SLSA project. These workflows run in an isolated job context that your repository's workflow file cannot tamper with.
Configuring the Generic Generator
For most compiled binaries or archives, the generic generator is the correct choice. Add the following job to your existing workflow. Note that permissions must be explicitly set to allow ID token writing and package access.
<!-- .github/workflows/release.yml -->
name: Build and Sign
on: [push]
permissions: read-all
jobs:
build:
runs-on: ubuntu-latest
outputs:
binary-hash: ${{ steps.hash.outputs.hash }}
steps:
- uses: actions/checkout@v4
- name: Build artifact
run: make build
- name: Generate SHA256 hash
id: hash
run: sha256sum dist/myapp > checksum.txt
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: myapp-binary
path: dist/myapp
provenance:
needs: [build]
permissions:
id-token: write # Required for OIDC signing
contents: read # Required to read repo metadata
actions: read # Required to read workflow info
uses: slsa-framework/slsa-github-generator/.github/workflows/[email protected]
with:
base64-subjects: "${{ needs.build.outputs.binary-hash }}"
upload-assets: true # Optional: attach to release A common mistake I see in 2026 is teams trying to pass the artifact file directly to the provenance generator. Do not do this. Pass only the digest. The generator does not need the binary itself to create the attestation; it needs the hash to bind the signature to the specific output. Passing files increases attack surface and wastes bandwidth.
Container Image Provenance
If you are building Docker images, use the container-specific generator. It integrates directly with the registry to push the attestation alongside the image tag. This is critical for Kubernetes deployments where admission controllers like Kyverno or OPA Gatekeeper will verify signatures at pull time. For teams deploying to EKS or GKE, see Amazon EKS practical guide or Google GKE practical guide for cluster-specific policy enforcement details.
How do you verify SLSA provenance before deployment?
Generating provenance is only half the battle. Verification must be automated and mandatory. In practice, I recommend integrating verification into three distinct gates: the CI pipeline (post-build), the artifact registry (admission), and the runtime environment (pre-deploy).
CLI Verification with slsa-verifier
The slsa-verifier tool is the standard for checking attestations. Install it in your deployment runner and fail the pipeline if verification returns a non-zero exit code.
# Verify a binary against its provenance
slsa-verifier verify-artifact \
--provenance-path myapp.intoto.jsonl \
--source-uri github.com/myorg/myrepo \
--builder-id https://github.com/slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@refs/tags/v2.0.0 \
dist/myapp
# Verify a container image
slsa-verifier verify-image \
--source-uri github.com/myorg/myrepo \
ghcr.io/myorg/myapp:v1.2.3 Notice the explicit --builder-id flag. This is non-negotiable. Without pinning the builder ID, an attacker could use a malicious fork of the generator to sign your artifacts. Always verify both the source repository AND the builder identity. This dual-check ensures the artifact came from your code AND was built by the trusted SLSA infrastructure.
What is the difference between SLSA Level 2 and Level 3 provenance?
Understanding the levels prevents over-engineering or under-securing your pipeline. Most teams should target Level 3 immediately, as the marginal effort over Level 2 is low when using managed CI systems.
| Feature | SLSA Level 2 | SLSA Level 3 |
|---|---|---|
| Build Service | Hosted, but not necessarily isolated | Hardened, isolated per-build environment |
| Provenance Generation | Can be generated by user script | MUST be generated by trusted builder service |
| Tamper Resistance | Signed, but content potentially influenceable | Non-falsifiable; user cannot inject fields |
| Signing Key | May be user-managed | Ephemeral, bound to workload identity (OIDC) |
| Audit Value | Basic traceability | Forensic-grade integrity evidence |
| Recommended For | Internal tools, low-risk libraries | Production apps, regulated systems, public OSS |
In my experience helping Nepali fintechs achieve ISO 27001 certification, Level 3 is often the minimum acceptable standard for financial software. Auditors specifically look for the "non-falsifiable" property. If your build script can write to the provenance file before signing, you have a Level 2 attestation at best, regardless of what the metadata claims. Always verify the builder ID matches a known Level 3 generator.
How do you integrate SLSA verification with Kubernetes admission control?
Verifying at deploy time is too late for high-velocity teams. Push verification left into the cluster using policy engines. This creates a defense-in-depth layer where even a compromised CI pipeline cannot deploy unsigned artifacts.
Kyverno Policy Example
Kyverno has native support for verifying Sigstore bundles. The following policy blocks any pod that references an image without valid SLSA Level 3 provenance from your specific builder.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-slsa-provenance
spec:
validationFailureAction: Enforce
rules:
- name: check-slsa-level3
match:
resources:
kinds: ["Pod"]
verifyImages:
- imageReferences:
- "ghcr.io/myorg/*"
attestors:
- entries:
- keyless:
url: https://fulcio.sigstore.dev
roots: |-
-----BEGIN CERTIFICATE-----
# Sigstore root CA here
-----END CERTIFICATE-----
issuer: https://token.actions.githubusercontent.com
subject: "https://github.com/slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@refs/tags/v2.0.0"
attestations:
- predicateType: https://slsa.dev/provenance/v1
conditions:
- all:
- key: "{{ buildDefinition.buildType }}"
operator: Equals
value: "https://slsa-framework.github.io/github-hosted/runners/v1" This configuration enforces that the OIDC issuer is GitHub Actions and the subject is the official SLSA generator. Any deviation fails admission. Combine this with Kubernetes RBAC hardening to ensure only the admission controller can bypass these checks during emergency break-glass procedures.
Implementing SLSA Provenance: Hardening Your CI/CD Supply Chain Step by Step
Adopting SLSA is an iterative process. Start with your highest-risk artifact—usually your primary production API or customer-facing frontend. Get Level 3 provenance working there first, verify it manually, then automate the gate. Only after that pipeline is stable should you expand to libraries and internal tools. Remember that provenance is only as strong as your weakest link; if you sign artifacts but skip verification at deployment, you have spent effort for zero security gain.
Supply chain security is not a feature you enable once; it is a discipline you maintain. As you mature, combine SLSA with SBOMs and vulnerability scanning for comprehensive coverage. If your team needs help designing a compliant, hardened pipeline architecture or auditing your current supply chain posture, reach out to discuss your specific requirements.