skip to content

Your nightly image's SBOM changes week to week with no code change - what explains it?

level: middleimportance: nice to knowfreq 33%

answer

  1. which artifact did each describe
  2. a tag is a pointer
  3. the observer can improve too
  4. scope decides which layers count
  5. record digest and generator version

basics

~20 s

Three things can move under you: the artifact, because a floating base-image tag now resolves to a different digest; the generator, because a new version added or renamed catalogers; and the options, because a different scope counts different layers.

solid answer

~50 s

Start by asking what the two documents actually describe. An SBOM's subject should be an image digest, not a tag - and a nightly build on a floating base tag pulls whatever that tag points at today, so a base rebuilt upstream changes your inventory without a single commit on your side. That is real change to a different artifact, not noise. The second cause is the generator itself: upgrading it adds catalogers, renames components, or improves identifier construction, so the diff reflects a better view of the same bits. The third is invocation: a scope that includes all layers rather than the final filesystem counts packages a cleanup layer deleted. Before you investigate anything, compare the subject digests and the generator versions recorded with the two documents. Only if both match are you looking at a genuine inventory change.

go deeper

for a junior

Know that an image tag can point at different content over time, so two SBOMs taken a week apart may simply describe two different images.

for a middle

Separate the three variables cleanly - subject artifact, generator version, invocation options - and explain how each one changes the output without any code change.

for a senior

Show how you make diffs trustworthy in a pipeline: record the subject digest and generator version with every document, fix the invocation, and resolve base references deliberately.

for a principal

Frame nightly SBOM diffing as a signal that only works once artifact identity is controlled, and be ready to say what you would spend to get there versus what the signal is worth.

## The question behind the question "Did the inventory change?" is meaningless until you know **what each document describes**. An SBOM is a statement about one artifact. If you name that artifact by a mutable tag, you have not identified it — you have identified a pointer. So the first move when two documents disagree is to compare their subjects. ## Three sources of a diff **1. The subject moved.** A nightly build that starts from a floating base tag resolves that tag at build time. Upstream rebuilds the base — for a patch, or on their own cadence — and the tag now points at a different digest with a different OS package set. Your build then produces a different image with a different inventory. Nothing about your code changed; the artifact did. The tell is simple: the two SBOMs describe different digests. This is also the mundane, non-malicious version of a serious concern. If a base image can change under you unnoticed, so can its contents, and the change arrives without review. Recording the resolved digest is what makes such a change visible as a fact rather than a surprise. **2. The generator moved.** Generators ship new catalogers, refine how identifiers are constructed, and fix parsers. An upgraded generator may report components the old one could not see, split what was one entry into two, or emit a different package URL for the same package. The bits on disk are identical; the observer improved. This diff is welcome, but it must not be mistaken for a change in what you ship — and it is why the generator's name and version belong recorded alongside the document. **3. The invocation moved.** Scope is the usual culprit: a squashed view describes the final filesystem, an all-layers view also counts things a later layer removed. A run in a different working directory, or against a source checkout rather than the built image, changes the answer for the same reason. Two engineers comparing outputs while running different commands will argue for an afternoon. ## How to make SBOM diffs meaningful - **Name the subject by digest.** Record the digest of the artifact the document describes, and diff only documents whose subjects you can identify. Comparing "last week's nightly" to "this week's nightly" is comparing two different artifacts. - **Record the generator and its version** with the document, so a diff can be attributed to the observer rather than the observed. - **Fix the invocation.** One command, one scope, run the same way in every pipeline, so a difference in output means a difference in the artifact. - **Resolve the base deliberately.** If the base is referenced by a moving tag, at minimum record which digest was resolved for each build; updating that reference on purpose turns base drift into a reviewable change rather than a nightly surprise. ## Reading the diff once it is trustworthy With subject, generator and invocation controlled, a diff is genuinely informative: a new transitive dependency appeared, a base-image update replaced a set of OS packages, a component you thought you removed is still present. That is exactly the signal you wanted when you started generating SBOMs nightly — a change log of what is actually inside the thing you ship. The reason it usually is not informative in practice is that teams start diffing before they have pinned down the other two variables, drown in false positives, and stop looking. ## Common wrong answers - "Generators are non-deterministic" — component ordering can vary between runs, which is a formatting nuisance handled by sorting before diffing; it does not add or remove components. - "Something must have been compromised" — jumping to attack before checking whether the artifact simply changed wastes the team's credibility. Establish the digest first, then investigate. - "It is a scanner bug" — usually it is the input, and the fix is in how the pipeline names its inputs rather than in the tool.

  • How do you tell a base-image change from a genuine dependency change in the diff?
    Look at which components moved. OS packages arriving and leaving as a block, with versions stepping to the distribution's current set, is a base change. Application-ecosystem components appearing or shifting version reflects your own resolution. If you also record the resolved base digest for each build, the two cases separate immediately without inference.
  • Your generator upgraded and the component count jumped by two hundred. How do you decide whether to be worried?
    Compare the same artifact digest with both generator versions. If the old and new tool disagree on identical bits, the difference is observation, and the new number is the better estimate of what you have been shipping all along. That is worth a look at the newly visible components for risk, but it is not an incident and no artifact changed.

Two stocktakes of "the warehouse on Elm Street" disagree. Before suspecting theft, check that both counts were taken in the same building, by the same method.

saying these in an interview costs you the question

  • Calls SBOM generation non-deterministic and stops there
  • Diffs documents without checking which digests they describe
  • Assumes a tag identifies one immutable artifact
  • Ignores the generator version when explaining a diff
  • Escalates to a compromise theory before checking the input

context