skip to content

A third-party build step pinned to a commit digest downloads a toolchain tarball at run time. What does the pin still guarantee?

level: middleimportance: must knowfreq 62%

answer

  1. the pin covers the reference, not behaviour
  2. what does the step fetch each run
  3. pinned bytes as a loader
  4. the step ships its own dependency tree
  5. hermeticity sits outside SLSA's Build track

basics

~20 s

A commit digest fixes only the step's own source at that revision. Whatever the step downloads while running - a toolchain tarball, an installer, packages - is unpinned, so the pinned code is a loader for unpinned code.

solid answer

~50 s

Pinning to a full commit digest is a strong guarantee but a narrow one: it fixes exactly the bytes of the step's own repository at that revision, so nobody can re-point a tag under you. It says nothing about what those bytes do once they run. A step that pulls a toolchain tarball from a release URL, an image by tag, or its own packages at run time is a loader: every build fetches code nobody pinned and runs it with your job's token, secrets and cloud identity. The pin is also silent about third-party code already baked into the step - a shipped bundle is produced from the maintainer's dependency resolution at their release time, not yours. So read the pin as integrity of the reference, then ask separately what the step downloads and what it already contains.

go deeper

for a junior

Know the two ways a step can be referenced and that a digest cannot be re-pointed while a tag can. Be able to say that a step runs inside your job with your job's secrets.

for a middle

Explain precisely what the pin fixes and what it leaves open: run-time downloads and the prebuilt bundle the maintainer resolved. Name at least one concrete way to pin a layer down.

for a senior

Show how you would inventory what builds fetch, then move from observation to a deny-by-default egress allow-list, and how you keep the fetching step out of the job that holds deployment or signing credentials.

for a principal

Own the tradeoff between build reproducibility and delivery speed: pre-baking toolchains into runner images and mirroring downloads costs platform effort, and you should be able to argue which pipelines are worth that spend and which are not.

## What a digest pin actually covers A third-party build step is somebody else's source code that your CI job checks out and executes on your runner, in the same environment as your build. Reference it by a mutable name - a version tag, a branch, a floating major - and the bytes you run are whatever that name points at on the day the job runs. Reference it by a full commit digest and the bytes are fixed: a digest is a cryptographic hash of content, so it is not a name that can be re-pointed, it is an identity that only one tree satisfies. That is a real guarantee and it closes a real attack. But it is a guarantee about **the reference**, not about **the behaviour**. It answers *which bytes do I start with*. It does not answer *what do those bytes do when they run*. ## The first unpinned surface: what the step fetches at run time Many build steps are thin. The pinned repository holds a few hundred lines whose job is to detect your platform and then download the real payload - a toolchain tarball from a release URL, an installer script, a container image by tag, packages from a public registry. Every build re-fetches it. **The pinned bytes are a loader for unpinned bytes.** Who can change those bytes without touching anything you pinned? - whoever can publish to that release URL - a compromised vendor account, or a compromised release pipeline at the vendor; - whoever sits in front of the download - a hijacked CDN or storage bucket, a lapsed and re-registered domain; - whoever controls the registry namespace the step installs from. If any of them succeeds, their code runs with your job's credentials: the repository token, every secret that job can read, the cloud identity it assumes, and write access to the artifact you are about to publish and sign. The signature will verify perfectly. You will have faithfully attested a compromised build. ## The second unpinned surface: the step's own dependency tree The other half sits inside the pin. A step that ships a prebuilt bundle had that bundle generated from **the maintainer's** dependency resolution at **their** release time, over a tree you never resolved and often cannot see as source in the repository. A digest proves the bundle has not changed since; it says nothing about how it was produced, from which versions, or whether one transitive package was compromised before the bundle was built. You are pinning a compiled artifact, and unless the step publishes provenance for its own release, nothing links that artifact to the source you can read. ## What to do about it Enumerate first, then constrain. 1. **Find out what your jobs download today.** Run builds behind an egress proxy in log-only mode and read the destination list. This is detective, and it is the step most teams skip. 2. **Pin one layer down.** Hold the tarball's expected checksum in *your* configuration, not read from the same server that serves the tarball. Reference images by digest rather than tag. Commit a lockfile if the step resolves packages at run time. 3. **Make the network the boundary.** A deny-by-default egress allow-list on the build job is the preventive control; better still, bake the toolchain into the runner image so the build downloads nothing. 4. **Shrink the blast radius.** A step that fetches at run time should not sit in the job that holds your deployment or signing credentials. 5. **Prefer steps that do not fetch.** Make *downloads code at run time* an explicit criterion when admitting a step at all. ## What this is not It is not fixed by climbing a maturity ladder. SLSA v1.0 splits its requirements into tracks, and the Build track (L0 to L3) is about the build platform: L1 asks for provenance describing how the artifact was built, L2 adds provenance generated and signed by a hosted build platform, L3 adds hardening so that the build's own steps cannot forge the provenance or reach the signing material. None of that constrains what a build fetches - hermeticity and source review sit deliberately outside the v1.0 Build track. Provenance will honestly record a build that pulled in a hostile tarball. Nor is it fixed by scanning the artifact afterwards. A scanner reports known-vulnerable components matched against advisories; code injected during the build has no advisory to match. And signing changes nothing on its own: a signature says who vouches for the bytes, not that the bytes are clean.

  • The step publishes a checksum next to the tarball it downloads. Does verifying that close the gap?
    Partly. It defends against tampering in transit or at a CDN, because the attacker would have to change both. It does nothing against a compromised upstream release process, which produces the tarball and its checksum together. It only becomes a real control when the expected checksum lives in your configuration, pinned and reviewed on change, rather than fetched from the same origin at run time.
  • How would you find out what your builds actually download today?
    Route build-job traffic through an egress proxy in log-only mode for a couple of weeks and collect destinations per pipeline. That gives you the real inventory rather than the one the workflow files imply. Then turn the observed list into a deny-by-default allow-list, starting with the pipelines that hold deployment or signing credentials, and treat every later addition as a reviewed change.
  • Would running the build at SLSA Build L3 prevent this?
    No. The v1.0 Build track hardens the platform and makes provenance non-forgeable by the build itself; L3 tells a consumer the artifact really came from that source on that platform. It does not restrict what the build pulls in while running - hermeticity is outside that track. The provenance would faithfully describe a build that fetched and executed hostile code.

A digest pin is a tamper seal on the envelope. It proves the letter was not swapped, and says nothing about the errands the letter tells you to run.

saying these in an interview costs you the question

  • Claims a digest pin makes the whole step immutable end to end
  • Treats a version tag and a commit digest as equally safe
  • Assumes the step only executes code from its own repository
  • Trusts a checksum served by the same host as the download
  • Says provenance or a signature would have prevented the fetched payload

context