SBOM

SBOM Drift Detection Playbook for 2026

A practical playbook for detecting and responding to SBOM drift between source, build, and runtime, with the patterns that separate signal from noise.

Aman Khan
Staff Engineer
6 min read

SBOM drift is the gap between what your manifests say you depend on, what your build actually produced, and what is running in production. Each of those three points should yield the same SBOM, and when they do not, you have either a benign packaging difference or evidence of supply chain compromise. The trick is telling the two apart, because the noisy false positives drown out the rare real signal unless you build the detection pipeline carefully.

This playbook captures what we learned running SBOM drift detection across a fleet that produces about 3,000 image builds per day. The patterns generalize, but the thresholds and tolerances will need to be tuned to your environment.

Where does drift originate?

Drift originates in three predictable places. The first is the gap between manifest and lock file, where a developer updates package.json or requirements.txt but the lock file is regenerated by CI with different transitive versions because of unpinned ranges. The second is the gap between build and image, where a base image rebuild pulls in different OS package versions because of upstream apt or apk repository updates. The third is the gap between image and running container, where in-place package installs or sidecar injection modify the runtime composition.

Each of these has a different risk profile. Manifest-to-lock drift is mostly benign and reflects normal dependency resolution, though it occasionally surfaces malicious typosquats. Build-to-image drift is usually benign but can mask supply chain attacks on upstream package repositories. Image-to-runtime drift is the most alarming because it indicates someone is modifying production containers, and outside of legitimate operator tools it almost always indicates compromise.

What should you generate SBOMs for?

The minimum viable SBOM coverage is one per build artifact: every container image, every binary, every deployable. SBOMs should be generated by the build system itself, signed with Sigstore or equivalent, and attached as attestations to the artifact registry. Generating SBOMs after the fact from a registry scan is a fallback, not a primary control, because it cannot detect dependencies that were present at build but removed before push.

Beyond the build-time SBOM, you want a source-time SBOM derived from the manifest and lock files, and a runtime SBOM derived from periodic introspection of running containers. The source SBOM uses Syft or equivalent to parse the manifests. The runtime SBOM uses an in-cluster agent that walks the package databases of running containers every few hours. Three SBOMs per artifact sounds like a lot, but the storage cost is trivial and the comparison is the whole point.

How do you compare SBOMs without drowning in noise?

A naive diff between two SBOMs produces thousands of lines of output because version metadata, file hashes, and component identifiers all vary in benign ways. The comparison logic that works treats components as identity tuples of (purl, version, supplier) and ignores cosmetic metadata. A component that appears in one SBOM and not another is a real difference. A component with a different file hash but the same purl and version is suspicious and worth investigating. A component with different metadata fields is noise.

We built our drift detection around three signal categories. Added components, where something appears in the later SBOM that was not in the earlier one. Removed components, where the opposite happens. And mutated components, where the same identity tuple has different file hashes. Added components in the build-to-image step are the most common drift type, mostly from transitive resolution. Mutated components in the source-to-build step are the most alarming, because they suggest a malicious version was injected during build.

When does drift indicate compromise?

The patterns that indicate real compromise are specific. A mutated component with the same version string but a different file hash is the classic supply chain attack signature, because it means the package contents changed without a version bump. We have seen this twice in production environments, and both times it traced back to a compromised package mirror. An added component in the image-to-runtime drift that is not in any expected operator allowlist is the second-strongest signal, because production containers should be immutable.

Conversely, the patterns that almost never indicate compromise are added transitive dependencies during build, version bumps within a manifested range, and metadata churn in OS package SBOMs. These categories account for about 96% of raw drift alerts in our environment, and a detection pipeline that treats them as high-priority will burn out the responding team within a month.

How do you operationalize the response?

The response workflow that scales has three tiers. Tier one is automated triage that classifies every drift event by category and routes the noisy ones to a logging-only stream. Tier two is automated investigation for the suspicious categories: the pipeline pulls the upstream package, compares hashes against public registries, and checks if the version is unexpectedly retracted or yanked. Tier three is human investigation for the small set of events that survive the first two filters.

We see about 4,200 drift events per day across the fleet. Tier one handles 4,050 of them automatically. Tier two handles another 140, mostly closing them as benign after the automated checks. Tier three sees about 10 events per day, of which one or two are worth a real investigation. That ratio is the goal: minimize human attention on noise and reserve it for the small set of events where it actually matters.

How Safeguard Helps

Safeguard ingests SBOMs at source, build, and runtime, automatically computing drift between adjacent stages. Griffin AI classifies each drift event by category and risk, suppressing the benign cases and surfacing the suspicious ones with context. Reachability analysis runs against drifted components, so you immediately see whether an unexpected new dependency is in a reachable code path. TPRM data flags drift events involving suppliers with poor historical hygiene, raising the priority of further investigation. Policy gates can block image promotion when drift is detected between source and build, and zero-CVE base images reduce the surface area of legitimate drift so the signal-to-noise ratio of your detection pipeline stays high.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.