Supply Chain Security: SLSA Framework
Supply chain attacks have moved from occasional headlines to daily concerns for developers, DevOps engineers, and security teams. When an attacker compromises a single dependency, the impact can cascade across thousands of downstream projects. The SLSA (Supply‑Chain Levels for Software Artifacts) framework offers a clear, tiered approach to harden the entire build and distribution pipeline, turning “trust‑by‑default” into “trust‑by‑verification.”
What Is SLSA and Why It Matters
SLSA is a set of best‑practice guidelines created by Google to help organizations assess and improve the integrity of their software supply chain. It defines four incremental levels (0‑3), each adding stricter controls over source provenance, build reproducibility, and attestation. By adopting SLSA, teams can prove that a binary was built from a known source, using a trusted process, and that no tampering occurred after the build.
Unlike ad‑hoc security checklists, SLSA is vendor‑agnostic and can be applied to any CI/CD system—GitHub Actions, GitLab CI, Jenkins, or custom pipelines. The framework also aligns with emerging standards like in‑toto, SPDX, and the OpenSSF’s supply‑chain security recommendations, making it easier to integrate with existing tooling.
Core Concepts of the Framework
- Provenance: Metadata that ties a binary back to the exact source commit, build environment, and dependencies.
- Reproducibility: Ability to rebuild the same artifact from the same inputs, ensuring that the binary is deterministic.
- Attestation: A signed statement (often a JSON Web Token) that declares the build met a specific SLSA level.
- Isolation: Running builds in environments that cannot be altered by external actors (e.g., containers, VMs, or hardware‑based enclaves).
Mapping SLSA Levels to Real‑World Practices
Understanding the four SLSA levels helps teams pick the right starting point and roadmap for improvement. Level 0 is “no requirements”—any artifact qualifies. Level 1 adds basic provenance, such as a commit hash and build script. Level 2 demands a hermetic build environment and source‑authenticated builds. Level 3 requires full reproducibility, automated provenance generation, and cryptographic signing of attestations.
Most organizations begin at Level 1 because the effort is low: enable source‑code linking in your CI system and store build logs. From there, moving to Level 2 typically involves containerizing the build and restricting network access. Level 3 is the gold standard and often requires adopting tools like in-toto or sigstore to generate verifiable attestations automatically.
Example: From Level 1 to Level 2 with GitHub Actions
name: Build & Publish
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
container:
image: ghcr.io/myorg/build-env:stable # hermetic container
options: --read-only # isolate filesystem
steps:
- name: Checkout source
uses: actions/checkout@v3
with:
fetch-depth: 0 # fetch full history for provenance
- name: Install dependencies
run: pip install -r requirements.txt
- name: Build wheel
run: python -m build
- name: Generate SLSA provenance
uses: slsa-framework/github-actions@v1
with:
artifact-path: dist/*.whl
slsa-level: 2
This workflow demonstrates two key Level 2 requirements: a read‑only container to guarantee environment immutability and an official SLSA action that emits provenance metadata. The fetch-depth: 0 flag ensures the full Git history is available, enabling precise source linking.
Pro tip: Pin the container image digest (e.g., ghcr.io/myorg/build-env@sha256:…) instead of a mutable tag. This prevents a malicious actor from pushing a compromised image to the same tag.
Generating Cryptographic Attestations (SLSA Level 3)
At Level 3, the build pipeline must produce a signed attestation that anyone can verify without trusting the builder. The OpenSSF’s sigstore project makes this straightforward by providing cosign for signing artifacts and rekor for storing transparency logs.
Below is a minimal example that builds a Docker image, signs it with cosign, and records the attestation in a Rekor log. The script can be run locally or as part of a CI job.
#!/usr/bin/env python3
import subprocess
import os
# 1️⃣ Build the Docker image
image = "ghcr.io/myorg/myapp:1.0.0"
subprocess.run(["docker", "build", "-t", image, "."], check=True)
# 2️⃣ Generate a short‑lived key pair (or load from CI secret store)
subprocess.run(["cosign", "generate-key-pair"], check=True)
# 3️⃣ Sign the image and upload attestation to Rekor
subprocess.run([
"cosign", "sign", "--key", "cosign.key", "--rekor-url", "https://rekor.sigstore.dev",
image
], check=True)
print(f"✅ {image} signed and attested")
The cosign sign command creates a JSON Web Signature (JWS) that includes the image digest, the builder’s identity, and a timestamp. Rekor stores this signature in an append‑only transparency log, enabling anyone to verify that the signature existed at a particular point in time.
Pro tip: Store the cosign.key in a hardware security module (HSM) or a cloud KMS. This prevents private‑key leakage even if the CI runner is compromised.
Integrating SLSA Attestations into Dependency Scanning
Generating attestations is only half the battle; downstream consumers must verify them before trusting a package. Tools like dependency‑track and anchore can ingest SLSA provenance and enforce policies such as “only accept Level 2 or higher artifacts.”
Here’s a quick Python snippet that pulls an artifact’s provenance from a public OCI registry and validates the SLSA level using the in-toto library.
import json
import urllib.request
from in_toto.attestation import AttestationVerifier
def fetch_provenance(image_ref: str) -> dict:
# OCI registry HTTP GET for the attestation blob
url = f"https://registry-1.docker.io/v2/{image_ref}/blobs/sha256:provenance"
with urllib.request.urlopen(url) as resp:
return json.load(resp)
def verify_slsa_level(provenance: dict, required_level: int) -> bool:
level = provenance.get("slsaLevel", 0)
if level < required_level:
return False
verifier = AttestationVerifier(provenance)
return verifier.verify() # cryptographic signature check
# Example usage
image = "library/python@sha256:abc123"
prov = fetch_provenance(image)
if verify_slsa_level(prov, required_level=2):
print("✅ Artifact meets SLSA Level 2")
else:
print("❌ Artifact does not meet required SLSA level")
This code demonstrates a lightweight verification step that can be added to a deployment script, CI gate, or even a runtime admission controller in Kubernetes.
Real‑World Use Cases
- Enterprise CI/CD compliance: A large financial firm mandated that all internal packages reach SLSA Level 2 before promotion to production, reducing the risk of supply‑chain malware.
- Open‑source distribution: The Python Packaging Authority (PyPA) started requiring SLSA provenance for wheels uploaded to PyPI, giving downstream users confidence in the origin of packages.
- Container hardening: A cloud provider integrated
cosignverification into its image scanning service, automatically rejecting images without a valid Level 3 attestation.
Automating SLSA Compliance Checks
Manual verification quickly becomes a bottleneck. Automation can be achieved by embedding policy-as-code tools such as OPA (Open Policy Agent) or Conftest into the pipeline. These tools evaluate JSON or YAML representations of provenance against declarative rules.
Below is an OPA policy that enforces a minimum SLSA level of 2 and ensures the builder identity matches an approved list.
package slsa.policy
allowed_builders = {
"github.com/myorg/ci-runner",
"gcb.googleapis.com/builds",
}
# Input is the provenance JSON
violation[msg] {
input.slsaLevel < 2
msg := sprintf("SLSA level %d is lower than required 2", [input.slsaLevel])
}
violation[msg] {
not allowed_builders[input.builder.id]
msg := sprintf("Builder %s is not authorized", [input.builder.id])
}
Integrate the policy with a CI step:
opa eval -i provenance.json -d slsa_policy.rego "data.slsa.policy.violation"
If the evaluation returns any violations, the pipeline fails, preventing the artifact from advancing.
Pro tip: Store your OPA policies in a version‑controlled repository and run opa test as part of every pull request. This ensures policy changes are reviewed just like code changes.
SLSA in Multi‑Cloud and Edge Environments
Supply‑chain security isn’t limited to data‑center builds. Edge devices, IoT firmware, and serverless functions also benefit from SLSA attestations. The challenge is the limited compute and storage on those platforms.
One approach is to generate a compact attestation (e.g., a short JWT) during the build and embed it directly into the binary’s metadata section. At runtime, a lightweight verifier checks the signature against a known public key before executing the payload.
For example, a Go‑based firmware image can include a signed manifest:
type Manifest struct {
Version string `json:"version"`
SLSALevel int `json:"slsaLevel"`
BuilderID string `json:"builderId"`
Signature string `json:"signature"` // base64‑encoded JWS
}
The device’s bootloader extracts the manifest, verifies the JWS using a pre‑installed root certificate, and aborts the boot if verification fails. This pattern mirrors the “secure boot” concept but leverages SLSA provenance for software supply‑chain assurance.
Common Pitfalls and How to Avoid Them
1. Treating SLSA as a one‑time checklist. Security is continuous; artifacts must be re‑validated whenever dependencies change.
2. Ignoring reproducibility. Without deterministic builds, you cannot prove that the signed artifact matches the source.
3. Storing keys in plain text. Even a Level 2 pipeline is vulnerable if the signing key is exposed. Use secret management solutions.
4. Over‑looking third‑party components. A signed internal binary is useless if it pulls in an unsigned, vulnerable library at runtime.
Pro Tip Checklist
- Enable
git verify‑commitandgit verify‑tagto ensure signed Git objects. - Adopt
reproducible-builds.orgguidelines for language‑specific toolchains. - Leverage
in-totolayout files to describe expected steps and artifacts. - Rotate signing keys regularly and enforce key expiration policies.
- Monitor transparency logs (Rekor, Grafeas) for unexpected attestations.
Future Directions: SLSA and Emerging Standards
The OpenSSF roadmap envisions tighter integration between SLSA, SPDX, and the Software Bill of Materials (SBOM) ecosystem. By coupling an SBOM with SLSA provenance, you can answer both “what is in this artifact?” and “where did it come from?” in a single, verifiable package.
Another promising area is the use of hardware roots of trust, such as TPMs or Intel SGX, to seal the build environment’s state. When combined with SLSA Level 3, this creates a chain of trust that extends from the silicon up to the deployed service.
Conclusion
Supply‑chain security is no longer optional; it’s a baseline requirement for modern software development. The SLSA framework provides a pragmatic, incremental path—from basic provenance to full cryptographic attestation—allowing teams to raise their security posture without a massive upfront overhaul. By embedding SLSA checks into CI pipelines, automating verification with tools like cosign, OPA, and in‑toto, and extending the model to edge and multi‑cloud scenarios, organizations can achieve robust, end‑to‑end trust in every artifact they ship.