The build platform should generate provenance, not the scripts it runs. SLSA v1.1 says that from Build L2 the provenance must come from the platform's control plane, and at L3 the signing secrets must be out of reach of the user-defined build steps. A script that writes its own provenance proves little.
This is a common design question when a team first adds provenance. The quick path is a script step that writes a JSON file. The sound path is to let the platform produce it.
Why the author matters
Provenance is useful because someone other than the code's author vouches for how the build ran. If the same steps that compile the code also write the record, a compromised step can write whatever it likes. The record would be signed, but it would reflect the attacker's story.
The L1 requirement is modest. It says the build process must generate provenance that identifies the output by digest, and it sets no authenticity bar. That is fine as a start, since it gives you something to compare later. It is not evidence against a determined attacker.
What changes at L2 and L3
According to the v1.1 requirements page:
| Level | Who produces provenance | Signing |
|---|---|---|
| L1 | The build process | Not required |
| L2 | The platform control plane, not tenants | Recommended, with a key only the platform component can reach |
| L3 | Same, strongly resistant to forgery by tenants | Signing secrets must not be accessible to the environment running user-defined steps |
The key phrase is "tenants." Your build steps are tenant code. The platform is the party you trust.
What this looks like in a pipeline
On a hosted CI system, you typically add a documented attestation step or feature rather than writing JSON yourself. GitHub's artifact attestation workflow, for example, uses a dedicated action and asks you to grant the job specific permissions. Whatever system you use, look for three signs the platform is the author:
- The provenance names a builder identity belonging to the platform, not to your repository.
- The signing identity is not a secret stored in your repository or passed to your scripts.
- You can describe, without hand waving, where the signing material lives.
If you cannot satisfy these, label what you have as L1 style provenance and say so.
A gradual path
Teams do not have to jump. A reasonable order:
- Record a build manifest in a script now, clearly marked as self reported.
- Switch to the platform's own attestation feature when your CI provider supports it.
- Move signing out of reach of build steps.
- Verify the result before deploy, checking builder identity and source.
Step one has value because it forces a decision about what to record. Just do not market it as more than it is.
How to describe it to a buyer
Say which party generates and signs the record, and at what SLSA level you assess the result, naming the spec version. Avoid "fully attested." If a customer asks, show a sample and the verification command.
Safeguard can pair that evidence with SBOM and dependency scan output, and you can try the free scan at https://gold.safeguard.sh/scan.
Quick check
Is a signed provenance file from my own script worthless?
Not worthless, but it is weak. It shows what the script claims, and a compromised step could claim anything.
Does L2 require signing?
The v1.1 page recommends it with a platform only key, and requires that the control plane generates the provenance.
Sources
- SLSA v1.1 build requirements (page marked retired, v1.2 is current)
- GitHub documentation on artifact attestations
Last reviewed: 19 October 2026.