Pinned Dependency Tracing in SBOM Queries
Tracing which dependencies actually shipped requires more than pinned versions and component lists.

Pinning a dependency version tells a package manager what to fetch. It says nothing about what actually got resolved, compiled, and shipped at build time. That gap, between the version you asked for and the version that ran, is where most SBOM queries quietly fail, and it's the reason a lockfile full of pinned versions can still leave a security team blind to what's actually running in production.
What an SBOM query traverses
An SBOM is a formally structured inventory of software components, but the inventory itself isn't the useful part. What matters is the relationship data that produces this inventory and lets you trace which intermediate package pulled in each dependency. Knowing that a project depends on some vulnerable logging library buried three or four layers down is useless if the SBOM can't tell you which intermediate package pulled it in, because that's the package you'd actually have to patch or replace.
That's the direct-versus-transitive distinction, and it drives remediation in a very practical way. A direct dependency can be updated directly, in the manifest, by the team that owns it. A transitive one requires tracing up the chain to whichever direct dependency introduced it, then updating that instead, or waiting for its maintainer to do so. A flat list of components with no depth information can't support that kind of remediation at all. It just tells you a bad thing exists somewhere in the tree.
Identity precision matters just as much as depth. A name and a version number are ambiguous on their own, since multiple ecosystems can produce colliding names, and version strings get reused or forked. Package identifiers and a standardized platform-naming scheme give a query engine something unambiguous to match against a vulnerability feed. Cryptographic hashes go a step further: they let a consumer verify that the component they're looking at hasn't been swapped or tampered with since the SBOM was generated.
The two dominant SBOM formats express these relationships differently, and this affects how the relationship graph functions as the canonical data structure rather than an afterthought. SPDX assigns every component an SPDXID and encodes relationships as explicit triples, DESCRIBES, DEPENDS_ON, CONTAINS, so the relationship graph is the canonical data structure, not an afterthought. SPDX is version 3.0.1 now, part of the 3.0 line that shipped in April 2024. CycloneDX takes a flatter, component-centric approach, keeping the component list clean and expressing dependencies through a separate array that maps each component reference to its dependents. CycloneDX 1.7 arrived in October 2025 and was adopted as ECMA-424 2nd Edition that December, the last release expected in the 1.x line, backward compatible all the way to 1.4. It added patent and IP metadata, citations for data provenance, and expanded cryptographic transparency.
Converting between the two formats can drop data along the way. When an organization needs both, the safer path is generating each directly from build metadata rather than converting one into the other after the fact. Dual output is cheap with current tooling, and most mature teams just produce both so no downstream consumer is stuck without the format they require.
Where build-time resolution breaks the chain of identity
Early SBOMs tracked static components: the libraries and packages sitting in a manifest. Modern SBOMs have had to expand to cover dynamic components generated during the build process itself, and that expansion introduces its own kind of noise. A build script that fetches a plugin at compile time, or a container base image that pulls a different patch version depending on when it runs, produces components that never appear in any static manifest.
A useful line has been drawn in the field between contextual SBOMs, generated by monitoring the build process as it happens, and core SBOMs, which just describe the software components themselves. These serve different query purposes, and conflating them is part of why so many SBOM queries return incomplete answers.
The build environment turns out to be a bigger hidden variable than most teams assume. A study of 5,298 Docker builds found that only 6.4% of rebuilt images matched the original set of installed package versions exactly (Malka et al.). Bitwise identity, the actual binary output matching byte for byte, was virtually never achieved. The causes trace back to factors in how builds are specified and how upstream repositories evolve over time, even when a lockfile hasn't changed.
There's a second layer to this problem that's easy to miss: if the SBOM tooling itself isn't reproducible, then none of the above holds. An SBOM tool counts as reproducible if it generates identical file content across repeated runs on the same input. Research has found that tools like Build-Info-Go and jbom fail this test, jbom in particular doesn't preserve element order and produces different component hashes run to run. That's a fixable engineering problem, not a fundamental one, but it shows the tooling ecosystem still needs consolidation before SBOM comparison can be trusted at face value. If the generator itself is noisy, a query comparing two SBOMs of the supposedly same build has no way to tell real drift from tool artifact.
How build-path attacks exploit the gap between listed components and what was actually executed
Supply chain attacks have surged by more than 300% since 2024, and the targets have shifted. Attackers in 2026 aren't just planting malicious packages on public registries anymore. They're going after build servers, CI/CD pipelines, code signing infrastructure, and the maintainers of open-source projects directly.
Two incidents illustrate why component-level SBOM checks miss this. The 2024 XZ Utils backdoor (CVE-2024-3094) and the 2025 Shai-Hulud npm worm both slipped past checks that only compare listed components against known-bad versions. Shai-Hulud spread by stealing developer npm credentials and hijacking CI/CD workflows, not by injecting a malicious package that anyone could have flagged by name. In both cases, the build or release path itself was subverted. The dependency list looked clean because, in a narrow sense, it was.
An SBOM query built only to check names and versions against a vulnerability feed would have returned a clean report for both. That's not a tooling failure so much as a scope failure: the attack surface was the process that produced the artifact, not the list of ingredients that went into it.
The stakes here are hard to overstate given how much of modern software is assembled rather than written. The Linux Foundation's Census II study found that modern applications contain somewhere between 70% and 90% open-source software by code volume, and the 2026 OSSRA report found only 2% of audited codebases contained no open-source components at all. CVE.org recorded 48,185 new CVEs in 2025. Continuous rescanning of deployed artifacts, not just scanning at build time, remains a valuable and underused step, precisely because a component that was clean at build time can become vulnerable the week after.
Cryptographic identity and build provenance added to a dependency trace
An SBOM lists what's in an artifact. Provenance proves how that artifact came to exist. The two are complementary, and neither substitutes for the other. Provenance supplies cryptographic, tamper-evident proof that a given build came from a known source, followed a defined process, and ran on a verified build system, none of which a component list can tell you on its own.
SLSA (Supply-chain Levels for Software Artifacts), maintained by OpenSSF, lays out a graduated path from L0 to L3 for increasing build and release integrity. SLSA v1.2, released in November 2025, introduced the Source Track, building on the concept of tracks first laid out in v1.0, with the Build Track the first to be fully defined. SLSA's own definition of reproducibility is exacting: repeating a build with the same inputs has to produce bit-for-bit identical output. That standard is what makes SBOM comparison meaningful in the first place, because without it, two SBOMs of "the same" build can differ for reasons that have nothing to do with an actual change in the software.
Hermetic builds, meaning builds run with no network access at all during the build step, came up as a point of debate at the 2025 S3C2 Summit. The tradeoffs of hermetic builds came up as a point of debate: they offer strong integrity guarantees, but are genuinely hard to pull off in practice, since so much tooling assumes it can reach the network. One approach to making hermetic builds more tractable is prefetching dependencies before the build step begins, so the build itself can run without network access.
A 2026 integrity framework combines three things: disclosure of the build procedure, reference evidence generated by an authority, and independent reproduction on the consumer's side. Together they catch post-generation tampering, repository-level substitution or rollback, and modification introduced at the distribution stage. That combination addresses something SBOMs alone can't: proof that a delivered SBOM actually, reproducibly corresponds to the software it claims to describe. Reproducible builds are, in effect, the only mechanism available for validating an SBOM through independent verification. Bootstrappable builds add a further layer of protection against "trusting trust" attacks embedded in the build toolchain itself. Together, the two provide an unbroken link between source code and the binary a user actually runs.
Build environment requirements for SBOM queries to trace pinned versions reliably
Here's the layer most queries miss entirely: a lockfile records what npm, pip, or cargo resolved. It says nothing about the version of the tool that ran the resolution. The Python interpreter, the Node.js runtime, the Rust toolchain, these often stay unpinned even on projects that are otherwise fastidious about locking application-level dependencies.
That unpinned layer produces real drift. Two developers running the identical lockfile on different machines can end up with meaningfully different transitive dependency trees, because the interpreter or toolchain resolving that lockfile isn't the same version in both cases. Following the same setup instructions across a laptop, a CI runner, and an automated agent routinely produces different runtime versions for the interpreter, toolchain, and system libraries, with few or none matching cleanly across all three. It's a structural gap in how teams define "pinned" version discipline, one that requires effort beyond simply asking developers to try harder. It's a structural gap in how most teams define "pinned" in the first place, one that stops at the application dependency layer and never reaches the runtime underneath it.
Nix-based environment tooling addresses this at the root by treating the whole environment, not just the application dependencies, as something to pin and reproduce deterministically. Nix uses functional programming principles to build environments that resolve the same way regardless of the machine running them. As of January 2025, Nixpkgs contains more than 122,000 packages, and its rate of package freshness outpaces any other package repository tracked. Devbox, built by Jetify on top of Nix, offers a searchable index of over 400,000 versions across roughly 80,000 packages, and lets a team reproduce the same test environment on a local machine and on a CI build host without hand-rolled shell scripts. Running devbox shell gets a new contributor into a working, pinned environment without them having to reconstruct the toolchain by hand.
The structural fix, then, is declarative environments: if the developer environment itself is defined declaratively, reproducible, isolated from other environments on the same machine, and consistent regardless of host operating system or processor architecture, the environment stops being an untracked variable in the SBOM query. Most of the traceability gap closes before the SBOM generator ever runs. Pair that with a build-native SBOM generator, one that records what was actually present during the build rather than what a manifest nominally requested, and the resulting SBOM reflects reality instead of intent.
Brandon Lum, Google's SBOM lead, has described the industry's task: build tools need to get better at propagating software metadata as a first-class output. The direction that implies is build-native SBOM generation rather than post-hoc scanning of a finished artifact. Some ecosystems are already moving that way. The Yocto Project's OpenEmbedded build system now generates SBOMs natively. Python maintainers explored build-native SBOM proposals in 2024, driven partly by SSDF and a major regional software security law. The Perl Security Working Group is exploring its own internal proposals, and similar conversations are underway in other ecosystems.
SBOM query tools consuming and surfacing transitive pinning data
Dependency-Track, an OWASP project, ingests CycloneDX SBOMs and correlates every component against vulnerability feeds, surfacing exploitability across the full dependency tree, transitive layers included, not just the top-level manifest. It integrates with GitHub Actions for automated SBOM upload and continuous scanning, so a new vulnerability disclosure gets checked against existing SBOMs without someone manually re-running a scan.
VEX, the Vulnerability Exploitability eXchange format, adds a filter on top of that: it tells a consumer which of the vulnerabilities present in the stack are actually exploitable in the context of how the software is deployed, letting a team focus remediation effort where it counts instead of chasing every known vulnerability entry that technically matches a component. India's CERT-In SBOM Guidelines 2.0, published in July 2025, specifically calls out VEX integration as a key goal for organizations adopting SBOM practices.
Those guidelines get specific, recommending SBOM adoption for government, public sector, and essential services organizations. They recommend SBOM adoption for government, public sector, and essential services organizations (the guidelines are advisory rather than statutory), and they specify that a complete SBOM should document at least 21 data fields per component, including multi-tier dependency visibility, cryptographic hashes, known vulnerabilities, and component origin. That's a direct specification of what a query has to be able to retrieve, not merely a suggestion to list top-level packages. It's a direct specification of what a query has to be able to retrieve, transitive layers and all.
CERT-In's guidance also addresses who gets to see the results. It recommends role-based access control, separation of public and private SBOMs, and restricting vulnerability detail to authorized parties. The enforcement burden sits with the query layer itself, not just with wherever the SBOM data is stored. OpenSSF has flagged continuous rescanning as valuable but underused across the industry generally, since new CVEs get discovered in packages that were clean at the last scan, and a one-time build-time check can't catch that. A systematic literature review out of Montana State University, covering 40 peer-reviewed studies, found that generation tooling quality, format and standardization gaps, false positives, hidden packages, and tampering all impede the query layer specifically. Mapped against the ISO/IEC 25019:2023 Quality-in-Use model, the deficiencies cluster around three areas: trustworthiness, usability, and fitness for security tasks, which is a fairly damning cluster for a technology that exists specifically to support security decisions.
The regulatory pressure that makes transitive traceability a compliance requirement, not a best practice
Regulators across multiple jurisdictions have converged on the same conclusion at roughly the same time. Cybersecurity authorities in Germany, India, Britain, Australia, and Canada, along with ENISA at the EU level, have each underscored the need for transparent, machine-readable software component inventories. In the US, a federal budget oversight body has required federal agencies to comply with a secure software development framework, which reinforces SBOM usage as a baseline expectation. A regional cybersecurity resilience law has come into force, cementing SBOMs as a structural requirement rather than an optional practice for software sold into that regional market.
CERT-In's July 2025 guidelines make SBOM adoption mandatory for government, public sector, and essential services organizations in India, while encouraging it as best practice elsewhere. In India's fintech backdrop, UPI fraud spiked 85% in fiscal year 2024, reaching ₹1,087 crore, and most of that traced back to vulnerabilities in third-party APIs and unpatched components that the organizations running them didn't even know were present. That's the exact failure mode a transitive, cryptographically verified SBOM query is built to catch.
What regulators are actually asking for goes well beyond a static component list. They want machine-readable inventories that stay current, integrate directly with vulnerability management workflows, and can serve as audit artifacts when something goes wrong. CERT-In's specific requirement for multi-tier dependency visibility and cryptographic hashes is, functionally, a mandate for the full query capability described throughout this piece. A flat list of direct dependencies simply does not satisfy it, no matter how current that list is kept.
The pressure isn't staying contained to software-native industries either. The US automotive sector and the medical device sector have both recognized SBOMs as necessary for managing their own sprawling supply chains. The automotive sector's recognition came through Auto-ISAC and the medical device sector's through IMDRF, with the FDA and NSA issuing supporting guidance. And per Kusari's predictions, open-source distributors are increasingly bundling SBOMs, SLSA attestations, and provenance data together rather than treating them as separate deliverables, which creates a feedback loop: gaps found in one feed a correction back into the other over time.
Requirements for genuinely traceable end-to-end pinned dependencies
Put the pieces together and the full chain looks like this: a declarative, reproducible build environment, feeding a build-native SBOM generator that captures cryptographic hashes and purls as the build happens rather than after the fact, wrapped in a provenance attestation under SLSA's Build Track, delivered in a format-faithful SBOM (SPDX 3.0.1 or CycloneDX 1.7, generated straight from build metadata rather than converted from one format to the other), queried continuously against vulnerability feeds with VEX filtering to separate real exposure from theoretical match, and delivered under access controls that respect who's actually authorized to see the result.
Pinning a version number was never the hard part. Any package manager can lock a version string into a manifest. What's hard, and what the regulatory and threat landscape of the past two years has made unavoidable, is proving that the version pinned in that manifest is the same version that got resolved, compiled, and shipped, by a toolchain whose own version was equally locked down, on a build system whose behavior can be independently verified. Every link in that chain that goes untracked is a link an SBOM query can't actually trace. An SBOM that can't trace its own chain offers only the appearance of visibility. It's offering the appearance of it.


