SLSA Provenance Generation for Nix Builds
Nix's hermetic builds need external attestation to meet SLSA requirements.

Generating SLSA provenance for Nix builds requires more than reproducible outputs. Nix supplies much of the build isolation and input control that SLSA demands, but those properties do not produce a signed account of a build. The remaining work is to turn build integrity into externally verifiable claims through tooling that the build itself cannot control.
Why Nix's build model maps naturally onto SLSA's requirements
Nix binds a build to declared inputs rather than leaving its behavior to the runner’s environment. Package sources are checked against cryptographic hashes, typically SHA-256, and flakes lock transitive inputs in a lockfile. That lockfile closes the mutable-channel problem that previously weakened reproducibility. The output path in /nix/store is derived from the build inputs, tying the artifact’s identity to its dependency closure. These properties give provenance generation a record of the inputs the build was meant to use.
The sandbox controls how those inputs become outputs. Builds run without network access or host environment variables, blocking the class of substitution in which a build silently retrieves a different dependency on another day. This isolation maps naturally onto SLSA’s requirement that the build platform be separated from the build. The stripped environment also supports the requirement that source define the build independently of the runner. These structural advantages alone are insufficient to meet every SLSA requirement.
The remaining boundary concerns who can make claims about the build. SLSA Build L3 requires provenance generation that the build cannot influence. Nix’s build model does not itself emit a signed statement identifying the platform, invocation and time of a particular execution. A reproducible artifact and an independently trustworthy account of its production are therefore separate deliverables.
What SLSA provenance actually requires that Nix does not emit
SLSA provenance is signed metadata. It records the builder’s identity, including the system, workflow and actor that triggered the build. It also describes the invocation, including the derivation, inputs and steps that ran. A cryptographic signature, produced through Sigstore or an equivalent mechanism, makes those claims externally verifiable. Nix supplies much of the underlying build information, but it does not supply this complete attestation on its own.
The hardest requirement is non-forgeability. If the build can alter the provenance generator or choose what it signs, the signature does not establish an independent account of execution. SLSA Build L3 therefore needs a trusted, isolated component that the build cannot tamper with. For GitHub pipelines, the integration described here routes attestation through a trusted reusable workflow outside the build job’s control. The placement of that authority matters as much as the metadata it emits.
SLSA v1.2, approved 24 November 2025, retains the Build track’s L0–L3 range and promotes the Source track from experimental to approved. The Source track covers source history and continuous tamper protection, so a flake lockfile supports part of its intent without replacing its attestation. The draft Build Environment track extends the scope to compute-environment integrity, including hardware-level measurement. The Dependency track addresses dependency ingestion, progressing from recorded identity to enforced ingestion and signed provenance, then protection against hostile dependencies subverting the record. Nix’s hash-verified inputs address important ingestion concerns, but evidence still has to be emitted and signed.
How the rebuild-from-source provenance model works in practice
Nix’s hermetic model also supports an independent way to test the relationship between source and artifact. The rebuild-from-source approach removes intermediate derivations while retaining downloadable, content-verifiable source packages. Those sources are exported to an offline system, where the build runs again from scratch. If the resulting digest matches the original artifact, verification no longer has to rely only on trust in the original runner.
The applicative-systems/secure-supply-chain repository demonstrates this pattern with a NixOS system image. It defines the image, checks source inputs for tampering and rebuilds offline. When the image digest is deterministic, a signed closure attestation can bind the shipping artifact to its dependency graph back to source. The scope is broader than a signature over an OCI image layer digest alone. The signatures differ in the evidence they cover as well as the format of the artifacts being signed.
Reproducibility still needs to be shown, even when it is expected. LTCI, Télécom Paris, Institut Polytechnique de Paris’s January 2025 study examined hundreds of thousands of packages from historical nixpkgs snapshots and found rebuildability rates in the high-majority range. Embedded build timestamps were a leading source of failures. Removing embedded build dates addresses a documented source of non-determinism, while equivalence can help assess some remaining differences without establishing byte-for-byte identity. Consequently, offline rebuilding strengthens provenance verification, but a failed digest match still requires explanation before reproducibility can be claimed.
Tooling that closes the attestation gap today
GitHub artifact attestations fit pipelines that already build and release through GitHub. arianvp/nix-attest records evidence at the derivation level. tiiuae/sbomnix derives component information from Nix’s dependency graph.
The SLSA framework suggests GitHub artifact attestations as an interim solution while it develops guidance and simpler replacement tooling. slsa-framework/slsa-github-generator is no longer actively maintained, with v2.1.0 from February 2025 its most recent release. The practical division of labor remains straightforward. Nix builds the artifacts, and a separate attestation mechanism records and signs claims about them. For the Build L3 non-forgeability requirement, that mechanism belongs in an isolated, trusted reusable workflow that the build job cannot influence.
arianvp/nix-attest uses a Nix post-build-hook to record build-time provenance through Nix and GitHub Actions. It records which derivation built a set of output paths, its build-time dependencies and the builder that ran it. It produces .slsa.json files for each derivation, which may have multiple output paths, giving release artifacts derivation-level provenance. This granularity suits teams that need to trace the individual derivations within a release. It does not remove the need to establish the isolation of the component that generates and signs trusted claims.
tiiuae/sbomnix generates SBOMs from flake references or store paths, while nixgraph queries and visualizes dependency graphs. Its vulnxscan tool demonstrates SBOM-driven vulnerability scanning.
SLSA provenance and SBOMs address different questions and both are required
SLSA provenance establishes evidence about origin and process. It lets a consumer check whether a binary came from source they can inspect, through the trusted build platform and process they expected. An SBOM, by contrast, lists the components, their versions and their licenses. It does not establish that the build producing those components was isolated or untampered. Treating either document as a substitute for the other leaves a different question unanswered.
This distinction matters operationally as well as for compliance. The EU Cyber Resilience Act is making SBOMs a requirement for compliance, so there is more pressure to produce that inventory. A provenance signature cannot stand in for it.
Nix makes both documents tractable because its closure is already a traversable dependency graph. sbomnix derives the SBOM directly from a flake reference or store path without a separate scanning step. The declarative manifest and pinned inputs can thus be used for both the inventory and the build evidence. The FOSDEM 2026 talk “Describing Nix closures using SBOMs” argued that this convergence is imperative for the ecosystem and illustrated closure-based SBOM generation.
The critical objection: reproducibility is not the same as security
A reproducible build can be faithfully and repeatedly malicious. If a compromised nixpkgs input contains a malicious upstream commit, Nix can build it exactly as declared. The same applies when a compromised source tarball is accepted as the pinned input. The output can have the expected hash and valid signed provenance and still be unsafe. Hash verification establishes only agreement with a declared input.
The S3C2 September 2025 Supply Chain Summit identified this distinction between process integrity and content integrity. It warned above all that SLSA compliance can give a false sense of safety when people mistake a build that ran correctly for software that is safe. Provenance can attest that the build was isolated, that inputs matched declared hashes and that execution followed the recorded process. It cannot show that no malicious commit entered upstream before the lockfile was pinned. Nor can it show that every dependency is free of known vulnerabilities.
Nix and protected provenance generation address build tampering, which is a significant category of supply chain risk. Upstream trust and vulnerable dependencies still need their own controls. SBOM-driven vulnerability scanning, including sbomnix’s vulnxscan, supplies one necessary layer. Its role is different from checking whether an attestation’s account of the build is trustworthy.
The S3C2 2025 Summit also discussed how to use provenance in AI and machine learning workflows, with agents as first-class identities and attestations for each training step. Those ideas broaden what provenance can cover, but the same limit still holds. Evidence that a process ran as declared is not evidence that its content is safe.
Putting the pipeline together: a practical path from Nix flake to signed SLSA attestation
A pipeline can start with a flake or environment manifest whose inputs are pinned and hash-verified. That declaration supplies the foundation for the later claims about source and dependencies. Nix then builds within its sandbox, preventing network access and host-environment leakage during execution. Before the result leaves the build environment, sbomnix generates an SBOM from the relevant flake reference or store path.
GitHub artifact attestations provide the GitHub-native route, while arianvp/nix-attest supplies per-derivation records where finer traceability is needed. In either case, meeting the Build L3 non-forgeability requirement depends on an isolated attestation path that the build job cannot influence. Sigstore signs the resulting provenance, with the attestation’s scope covering the artifact and its dependency closure where that closure model is used. A signature cannot supply missing scope or compensate for a generator controlled by the build.
The deployment then carries the input-derived hash together with the evidence describing its origin and contents. This connection supports CVE discovery and hash-level blocking or patching without reconstructing dependencies from logs or rescanning images. In the minimal-image case, an OCI container contains only the application and its exact declared dependencies, with no inherited base-image contents. The closure, SBOM and attestation can then describe the same shipping unit.
Teams can adopt these controls incrementally without abandoning their existing CI or deployment infrastructure. The lockfile and sandbox establish input control and build isolation, but they are not substitutes for the provenance required by SLSA build levels. For regulatory or high-security settings, applicative-systems/secure-supply-chain provides a reference for adding offline rebuild verification. The resulting pipeline separates three responsibilities clearly, namely controlling the build, documenting its contents and issuing claims that the build cannot forge.


