skip to content

A .deb build's provenance carries no resolvedDependencies — what may a verifier conclude?

level: seniorimportance: should knowfreq 42%

answer

  1. optional field, incomplete by design
  2. silence, not a negative claim
  3. empty array equals missing key
  4. can falsify, never confirm completeness
  5. consumed by the build, not shipped

basics

~10 s

Only that the inputs were not stated. SLSA v1 makes resolvedDependencies optional and allows it to be incomplete, so an absent or empty list means unknown, never that the build consumed nothing.

solid answer

~50 s

`resolvedDependencies` is an optional, unordered collection of artifacts the build consumed — for an OS package build that would be the base image, the toolchain, and the fetched source tarball, each entered with a URI and/or a digest. SLSA v1 explicitly allows the collection to be incomplete, and the build track does not require completeness, so its absence is silence rather than a negative claim: no packages were listed, not no packages were used. An empty array is no better than a missing key; never read emptiness as a clean bill of health. Use the entries that are present — a listed base image digest can be checked against your approved set — but never conclude that nothing else was pulled in, so a fleet-wide argument that no compromised upstream mirror fed these builds must rest elsewhere.

go deeper

for a junior

Know that resolvedDependencies lists artifacts the build consumed, such as a base image or a fetched tarball, and that it is optional so it may simply not be there.

for a middle

Be ready to say why the spec allows the collection to be incomplete and why an empty list therefore carries no information about what the build actually pulled in.

for a senior

Show the asymmetry in how you use it: a listed digest that is not on your approved list is a hard fail, but a short list never proves nothing else was consumed. Say what you fall back on.

for a principal

Own the decision of whether your organisation demands input completeness at all, given that the build track does not require it and getting it depends on the platform's own guarantees rather than the format.

## What the field is for `resolvedDependencies` lives inside `buildDefinition` and holds an unordered collection of the artifacts a build needed while it ran. Each entry is a resource descriptor: a URI, a digest map, optionally a name or media type. For a pipeline producing an OS package, the natural candidates are the base image the build ran in, the compiler and packaging toolchain, the upstream source tarball that was fetched, and the package feeds consulted for build-time dependencies. The word *resolved* is the point. `externalParameters` may say "build the ref `release-3.2`" or "use the config at this path"; `resolvedDependencies` records what those references actually turned into — the concrete digest that was fetched. That is why a listed entry is genuinely useful evidence: it converts a mutable reference into a fixed identity that you can compare against an expectation. ## Why absence is not a claim The field is **optional**, and the specification is explicit that the collection **may be incomplete**. The build track does not oblige a platform to enumerate everything a build touched — doing so is genuinely hard, since a build can reach for files through paths no framework observes. So three states exist and only one of them is informative: | What you see | What it means | | --- | --- | | entries present | those specific artifacts were consumed; compare their digests | | empty array | nothing stated — not a claim that nothing was consumed | | key absent | nothing stated — identical practical meaning | The temptation to distinguish empty from absent is strong and should be resisted. Neither is a positive assertion, and a rule that accepts an empty array as "no third-party inputs" is inventing evidence. Every build consumes a toolchain at minimum; an empty list is a statement about the emitter's diligence, not about the build. ## What this costs you in a fleet scenario Suppose you operate a fleet that installs OS packages built by an internal distro pipeline, and you want to answer a question about a class of risk: could a compromised upstream mirror have fed a substituted source tarball into these builds? If `resolvedDependencies` lists the tarball's digest, you have a strong partial answer — you can compare that digest against the one the upstream project publishes. If the field is empty, you have nothing from the provenance and must fall back to other evidence: whether the fetch step verified a digest itself, whether the mirror was authenticated, whether the base image came from an approved registry. Notice the asymmetry, because interviewers probe it. Present entries can **falsify** an expectation — a base image digest that is not on your list is a hard fail. Absent entries can never **confirm** one. A verification design should therefore treat this field as a source of disqualifying evidence, not as a completeness proof. ## Direction and neighbours Two confusions are worth heading off. First, direction: `resolvedDependencies` is what went **into** the build; `byproducts` in `runDetails` is what came **out** alongside the artifact, such as logs and reports. Putting a build log in the dependency list is a common misreading of a real document. Second, scope: this is a record of what the build *consumed*, which is not the same as what the artifact *contains*. A compiler and a test harness are consumed but do not ship; vendored code may ship without appearing here at all. If your question is "what is inside this package", the provenance predicate is the wrong document to be reading, and treating the dependency list as an inventory of shipped components is how teams end up scanning the wrong set. ## What a good answer sounds like "Present entries I compare; missing entries I treat as unknown and note as a gap in what the platform states. If my policy actually requires knowing every input, that requirement has to be met by the build platform's documented guarantees for this build type, not inferred from an empty array."

  • What does a single resolvedDependencies entry actually contain?
    A resource descriptor: typically a URI identifying where the artifact came from and a digest map pinning its content, plus optional extras such as a name, media type or annotations. At least one identifying member has to be present. The digest is the load-bearing part for verification, because a URI alone names a location whose content can change while a digest fixes the bytes.
  • Where in the predicate would a build log or a test report be recorded?
    In `runDetails.byproducts`, which collects additional outputs of the run that are not the artifact being attested. The direction is the opposite of `resolvedDependencies`: dependencies went into the build, byproducts came out of it. Mixing the two is a frequent misreading, and it matters because a log listed as an input would imply the build consumed something it actually produced.
  • Two builds list identical resolvedDependencies but produce different artifacts. What do you conclude?
    That the recorded list is incomplete or something undeclared varied — an ambient tool version, a network fetch nobody recorded, a timestamp baked into the output. It is direct evidence that the stated inputs do not determine the result, which undermines any expectation you wrote over those fields. The next step is finding what varied, not adjusting the expectation to accept both.

saying these in an interview costs you the question

  • Reads an empty resolvedDependencies as proof of no external inputs
  • Assumes the list is complete because the build platform is trusted
  • Treats the dependency list as an inventory of what ships in the artifact
  • Distinguishes an empty array from a missing key as if it were a claim
  • Puts build logs in resolvedDependencies rather than byproducts

context