TT Lab
Get started
Learn Learning paths Courses

The Build Was Green — So Who Put That Library In?

Nobody knows where these bytes came from

Continue in TT Lab

In one line

Provenance records "what was made from what, by whom, and when" at build time, and SLSA divides how far you can trust that record into levels.

Why this matters

Even with a list and a signature, one question remains unanswered: "where did these bytes come from?" A signature answers "who signed this?" and an SBOM answers "what is in it?", but neither tells you which source the artifact came from and through what procedure.

The scene where this question actually becomes a problem is not dramatic. Usually it goes like this: in a hurry, someone built on their own laptop and uploaded it, and that artifact also carries a signature with the company key. The signature passes. The list is attached. But nobody knows which commit that build came from or which dependencies it used. When a problem arises months later, there is not a single thread to trace back.

How it works

SLSA divides this into tracks and levels. In the Build track, L0 means no guarantee at all, and L1 means a provenance exists that records how the artifact was built. An L1 attestation may be incomplete or unsigned, so it prevents mistakes but not forgery. L2 means a hosted build platform on dedicated infrastructure generates and signs the attestation, and so it prevents tampering after the build. L3 hardens the build platform itself so that runs cannot influence each other and the secret used to sign attestations cannot be touched by user-defined build steps (SLSA security levels). The v1.0 version of this levels document is currently marked 'Retired' and points to a newer version — something to check when you cite it.

The attestation uses the in-toto Statement shape. At the top are _type and subject, and predicateType points to the kind of predicate. The SLSA documentation insists that you put in https://slsa.dev/provenance/v1 exactly as written, not the address shown in the URL bar. The inside of the predicate is split in two.

buildDefinition   무엇을 만들라고 했는가
  buildType            이 칸들을 어떻게 읽어야 하는지 가리키는 URI
  externalParameters   빌드에 밖에서 넣은 값 (소스 주소와 커밋, 진입점 등)
  internalParameters   플랫폼이 스스로 채운 값
  resolvedDependencies 실제로 쓴 재료와 그 다이제스트

runDetails        누가 언제 실행했는가
  builder.id           이 빌드를 수행한 플랫폼의 신원
  metadata             invocationId · startedOn · finishedOn

What the documentation lists as required for Build L1 are buildDefinition and runDetails, and within them buildType and externalParameters, and builder (SLSA Provenance v1). The rest are fields that are nice to have. In particular, the documentation separately explains that builder.id is the field that carries the whole trust boundary — because it is a declaration that you trust the platform that identifier points to.

The value of resolvedDependencies lies in recording a digest with each material. If you write only names, you cannot ask "if we rebuild from the same inputs, do we get the same thing?" With digests, you can ask that question later, even after an incident.

What it looks like in the field

The first trap is producing attestations that nobody reads. The pipeline spits out one more JSON file and ends by uploading it to the artifact repository. Unless there is a procedure to open that file right before deployment, that attestation changes nothing just by existing.

The second is pouring the entire build environment into externalParameters. The documentation recommends keeping this field to a minimum. The more values there are, the harder it is for the verifier to define "what is normal", and in the end it becomes a big lump that nobody compares.

The third is writing a branch name instead of a commit hash. A branch is a moving pointer, so the same attestation would point to a different source at different times. You must pin it with a digest.

The fourth is confusing who creates the attestation. An attestation has value only if it is created by the party that performed the build. An attestation filled in by hand after the build finishes records only what that person knows, and if that person is deceived, the attestation is deceived along with them. This is why SLSA narrows 'who creates the attestation' as the levels go up — at L2 the hosted platform creates and signs it, and at L3 the signing secret is out of reach of user build steps.

What you will check in the next quiz

You check what each level of the Build track prevents, which fields of the attestation are required for Build L1, and why builder.id is the field that carries the trust boundary. In the following modules, you actually create and sign this attestation and even set up a gate that reads it.