The Build Was Green — So Who Put That Library In?
No evidence, no deploy
In one line
The list, the signature, and the attestation are the same as nonexistent if they are not read right before deployment, and the value of a gate comes not from what it blocked but from whether a person can read why it blocked.
Why this matters
Everything built in the previous three modules is evidence. A list of what is in it, a signature saying these bytes are ours, and an attestation recording where they came from. But evidence does nothing unless it is submitted to the court. The procedure that opens it right before deployment and stops if it falls short is the gate.
The mistake people make most often when building a gate is looking only at the signature. Signature verification says only "these bytes were signed with this key". Whether that key is ours, whether the attestation that signature is attached to really came from our builder, and whether the subject the attestation points to is exactly the file we are about to deploy now are each separate questions to ask. If even one of the three is missing, a path opens for something to pass.
How it works
The questions the gate asks boil down to four.
목록이 붙어 있는가 SBOM 이 있고 비어 있지 않은가
서명이 맞는가 우리가 믿는 키로 검증되는가
대상이 같은가 증명의 subject 다이제스트가 지금 이 파일의 해시와 같은가
빌더를 허락했는가 builder.id 가 허용 목록에 있는가
The fourth line is often missing, and in practice that is where the quietest breaches happen. When the signature is right and
the digest is right but the build came from someone's laptop, a gate that looks only at the first three
lets it straight through. This is why SLSA requires a hosted platform on dedicated infrastructure at Build L2 —
because where it was built is itself a security property
(SLSA security levels). cosign's verification looks in the same direction. The documentation says
cosign verify checks not only the signature but also whether the signing certificate came from a trusted
certificate authority
(cosign verification).
Another important design choice is to leave the reason as a code. If you emit failure messages only as sentences,
each person writes them differently, and then you cannot count "what blocked us most last month".
If you leave short codes such as signature_missing or builder_not_allowed, the verdicts
become statistics as they are, and with statistics, what to fix next is decided by numbers rather than arguments.
Finally, you must build a place for waivers into the gate. A gate with no exceptions gets switched off entirely when things are urgent, and a gate that has been switched off does not get switched back on. If you make exceptions leave a record, the gate stays on.
What it looks like in the field
The most common failure is a gate that only warns and does not stop. A yellow line remains in the pipeline log and the deployment proceeds as is. It starts with the reason "until we get used to it", and after that nobody reads that line. A gate that does not stop is not a gate.
The second is not checking the passing case first. If you test the blocking first, even a gate that 'always blocks' looks successful. You have to pin down first that a normal release passes, and then build the cases that should be blocked one by one, so that both directions are confirmed.
The third is not leaving the verdict. The fact that the gate blocked something exists only on the screen at that moment, and weeks later when someone asks "why did it block then?", nobody can answer. If you record the verdict, the basis, and the subject's digest in one line, that question becomes one you can answer.
The fourth is placing the gate too late. If you check only at the moment of deployment, the release is already scheduled and people are gathered, and the moment it gets blocked, someone says let's turn off the gate. If you run the same check once right after the build as well, the problem shows up hours earlier, and the check right before deployment becomes closer to a confirmation. It is just calling the same program from two places, so it costs almost nothing.
The fifth is the gate producing the evidence it looks at itself. If you regenerate the SBOM right before deployment and check that, that list is not what the build actually used but what you just unpacked again. The day the two diverge is exactly the day you wanted to catch, and that divergence becomes invisible. Evidence should be attached by the party that produced it, and the gate should only read.
The sixth is the order in which you turn the gate on. If you enforce all four checks at once from the start, every existing release gets blocked, and the gate is turned off that day. The order that survives in practice is to keep a short period of only recording reasons, look at which reasons occur and how many times as numbers, and then switch them to enforcement one at a time. Even then, you must also pin down a date saying "by when everything becomes enforced" — without a date, the record-only period never ends.
What you will do in the next lab
You attach a provenance to a release bundle and sign it, then build a gate that checks four things and blocks with a reason code. After first confirming that the normal bundle passes, you build three bundles yourself: a bundle with no signature, a bundle whose artifact was changed, and a bundle with a valid signature built by a builder you did not allow, confirm that each is blocked for a different reason, and leave those verdicts as an audit record.