Skip to content

Building a DevSecOps Evidence Chain: SBOM, Provenance, Deployment, and VEX

A finding just landed: CVE-2024-29025 against pkg:maven/io.netty/netty-codec-http@4.1.107.Final in your payments-api SBOMSoftware Bill of MaterialsA machine-readable inventory of the components and dependencies included in a software product.. Before you page anyone or file a ticket, you need one answer: is the affected artifact running in production right now? In my experience, most teams cannot answer that in under an hour. The evidence is scattered across a scanner output, a deployment manifest, and a Slack thread from last Tuesday.

This walkthrough closes that gap. It is the implementation companion to From SBOM to Actionable Signal. Where that article defines the evidence-to-decision model, this one walks through how I run it for a single service and finding. One manual pass, start to finish, keeping enough raw evidence at each step for another person to reconstruct the reasoning.

The operating model below is derived from the sources cited in this guide. It is practical guidance, not a standard, scoring engine, or proof of exploitability or safety.

The evidence-to-decision model with stages 1 through 4 highlighted — the evidence collection chain. The evidence-to-decision model with stages 1 through 4 highlighted — the evidence collection chain.
  • Each row answers a different question. No single input is a verdict.
  • unknown is a valid outcome when a required join or assessment is missing.
  • The arrows are evidence links for review, not an automatic decision.

The NTIA SBOM minimum-elements report defines an SBOM as a formal record of software components and their supply-chain relationships. CISA’s 2026 SBOM guidance also treats coverage and known unknowns as part of an SBOM practice.

Use that information as component-inventory evidence. Do not infer that an artifact is deployed, that its inventory is complete, or that vulnerable code is reachable. An absent component in an SBOM is not proof that it is absent at runtime — a gap explored in Why Your SBOM Does Not Protect You.

Before collecting more data, make the outcome explicit. You will remediate, deprioritize with evidence, or accept risk for a bounded period. unknown is the required intermediate outcome whenever a join or assessment is missing.

Six evidence classes stacked from component identity to reachability context, each with its key question. Six evidence classes stacked from component identity to reachability context, each with its key question.

Here’s what I do: one manual walkthrough

Section titled “Here’s what I do: one manual walkthrough”

The goal is narrow: determine whether the exact affected artifact is observed in production, preserve uncertainty, and record a reviewable next action.

Input: the advisory and the payments-api SBOM entry. Retain: advisory identifier, component identity, SBOM reference, issuer, generation time, coverage, and known unknowns. Answered: what component did the finding name, and in which declared inventory? Not yet answered: whether the inventory is complete, the component is deployed, or it is exposed, reachable, or exploitable.

This boundary matters. An SBOM is component-inventory evidence, not runtime evidence. Its coverage and known unknowns make an absent or missing match interpretable rather than silently clean. The NTIA SBOM minimum-elements report and CISA 2026 SBOM minimum-elements guidance support that inventory and disclosure boundary.

Input: the affected component’s releasable artifact. Retain: an immutable OCIOpen Container InitiativeA governance structure for open standards around container formats, runtime specifications, and image distribution. digest, the object type it identifies, and registry context. Answered: which specific content is joined to the finding? Not yet answered: who owns it, which environment it targets, whether it is authorized, running, or secure.

For OCI content, a digest is a content identifier based on a collision-resistant hash of content bytes. I use that digest, not a mutable tag, as the join key between the artifact, its provenance, and deployment observations. A digest identifies content. It does not establish operational state.

Input: the provenance attestation and the recorded digest. Retain: attestation reference, verification result, signature check, subject digest, predicate type, builder identity, and trusted level. Answered: did the retained attestation verify for this artifact under your trust boundary? Not yet answered: whether the artifact is deployed, safely configured, reachable, or exploitable.

SLSA provenance describes where, when, and how an artifact was produced. SLSA’s verification guidance covers checking the signature, subject, predicate, builder, and trusted level. SLSA Build L3 adds hardened-build-platform controls within its threat model; it is not a runtime-security or exploitability certificate. Available but unverified provenance provides none of that claimed build assurance.

Input: the intended deployment reference and an independently collected runtime observation. Retain: both identities, workload, environment, collection method, and observation time. Answered: what was intended to run, and what was observed at a stated time? Not yet answered: whether every instance is current, healthy, exposed, or represented by this observation.

Desired and observed state answer different questions, and an observation can be missing or stale. On Kubernetes, an image can be specified by digest, while ContainerStatus.imageID is a runtime-resolved identifier that may differ from the Pod specification’s image identifier. That Kubernetes detail is platform-specific, not a universal deployment API.

Input: a VEXVulnerability Exploitability eXchangeA security advisory that communicates whether vulnerabilities affect a specific product and why. (if one exists), plus locally collected exposure and reachability evidence. Retain: VEX issuer, product and version match, date, revision history, status, and justification; for exposure and reachability, retain method, coverage, and uncertainty. Answered: what attributable product-status assessment and bounded local context are available? Not yet answered: whether the evidence independently proves safety or exploitability.

The CSAF 2.0 VEX profile defines statuses including fixed, known_affected, known_not_affected, and under_investigation, and requires lifecycle tracking and revision history. Treat a VEX as attributable, revisable product-status evidence: match it to your product and version, and keep its justification. VEX: Documenting “Not Exploitable” examines each justification flag and what it commits a supplier to.

I always record the reachability method and its blind spots alongside the result. A study on static vs. dynamic analysis of Java dependencies found that static analysis misses dynamic behavior like reflection while dynamic analysis only covers paths your tests actually exercise. That study applies to one language ecosystem. When I fill in this step for a Go or Python service, I note that those findings do not transfer directly and state what my local analysis method can and cannot see.

Input: the linked records and their stated limitations. Retain: local outcome, accountable owner, timestamp, raw-evidence links, and expiry or reassessment trigger. Answered: what decision can you defend right now? Not yet answered: whether later evidence or changed operating context invalidates it.

This is a local, reviewable judgment. Assign evidence owners: the build owner for the digest and provenance record, the platform or service owner for the deployment observation, and an application or security owner for exposure and reachability context. A VEX revision, artifact or deployment change, exposure or configuration change, or improved analysis must reopen the record.

Evidence handoff chain: six steps from finding to decision, each retaining a record, naming an owner, and keeping uncertainty visible. Evidence handoff chain: six steps from finding to decision, each retaining a record, naming an owner, and keeping uncertainty visible.
finding:
advisory_id: CVE-2024-29025
component: pkg:maven/io.netty/netty-codec-http@4.1.107.Final
sbom_ref: evidence://payments-api/sbom/2026-08-02
sbom_boundary: "coverage and known unknowns retained"
artifact:
digest: sha256:9b2e4a7f3c1d
object_type: oci-image-manifest
registry_context: ghcr.io/acme/payments-api
provenance:
attestation_ref: evidence://payments-api/provenance/4.1.107.Final
verification: passed
trust_boundary: approved-builder-policy
deployment:
intended_ref: ghcr.io/acme/payments-api@sha256:9b2e4a7f3c1d
observed_runtime_id: runtime://payments-api/pod-7/sha256:c4d8e2f1a9b3
workload: payments-api
environment: production
observed_at: 2026-08-02T09:30:00Z
observation_method: independently-collected-runtime-observation
context:
vex_status: under_investigation
exposure_evidence: evidence://payments-api/exposure/2026-08-02
reachability:
method: documented-local-analysis
coverage: bounded
uncertainty: "not a proof of exploitability or safety"
decision:
outcome: unknown
owner: payments-api-service-owner
reassess_on:
- VEX revision
- artifact or deployment change
- exposure or configuration change
- improved analysis
evidence_links:
- evidence://payments-api/finding/CVE-2024-29025
- evidence://payments-api/raw-records

Here, passed reports the provenance-verification result only. It does not decide the vulnerability. unknown remains the outcome until the required local evidence has been assessed.

Evidence ownership matrix showing who produces, reviews, decides, and reassesses each evidence class. Evidence ownership matrix showing who produces, reviews, decides, and reassesses each evidence class.

Choose an outcome branch only when its evidence exists

Section titled “Choose an outcome branch only when its evidence exists”

Both branches are decision paths, not severity rules or universal policy — Responding to a Critical CVE provides a routing checklist for each. In either case, retain the original finding and links to the raw evidence.

Use this branch when the observed production identity maps to the affected digest, no applicable evidence changes the product assessment, and your local exposure and risk review supports urgent action. Record a remediation owner and target artifact, then re-observe the new deployment identity after the change.

An SBOM match, provenance result, exposure record, or reachability result does not independently prove exploitability. The branch records a local decision based on the joined evidence and your review.

Use this branch only when an attributable, dated, version-matched VEX or equivalent local assessment is retained with its justification and local context. Record the evidence, accountable owner, bounded expiry, and concrete reopening events.

known_not_affected is not an unaudited suppression switch. A missing product match, missing justification, stale context, or unresolved assessment returns the record to unknown, not to deprioritization. This is consistent with the CSAF VEX profile, whose statements remain attributable and revisable rather than permanent truth values.

Gate: complete the walkthrough once. If a reviewer cannot reconstruct the finding-to-outcome path from raw evidence, timestamps, owners, uncertainty, and reassessment triggers, you are not ready to automate.

Good automation candidates are deterministic work:

  • Retain references and timestamps at each step
  • Check whether an attestation subject matches a recorded digest
  • Collect intended and observed deployment identities
  • Detect missing mandatory fields
  • Link updated VEX versions and reopen records when a listed trigger fires

Keep human review for exposure and reachability interpretation, the adequacy of a VEX for your product and context, risk acceptance, final disposition, and remediation authorization. I’ve seen teams jump to automated suppression before they had one clean manual path. The result is fast-looking answers that no one can reconstruct six months later.

Decision lifecycle: remediate, deprioritize, accept risk, or unknown — new evidence or expiry reopens any documented decision. Decision lifecycle: remediate, deprioritize, accept risk, or unknown — new evidence or expiry reopens any documented decision.
  • Using a tag as the join key. A tag is mutable. A digest is not. They are not equivalent identifiers.
  • Keeping an attestation without verifying it. Unverified provenance provides none of the claimed build assurance.
  • Equating desired state with observed state. A deployment declaration and a runtime observation answer different questions.
  • Suppressing findings from VEX status alone. VEX must be matched, attributed, dated, and reviewed in your local context.
  • Recording a rationale without an expiry. A decision without a reassessment trigger outlives its supporting assumptions.

Before you automate anything, confirm these five things for one service:

  • Your SBOM includes a stated boundary, coverage, and known unknowns.
  • Each finding is linked to a component identity and immutable artifact digest.
  • Provenance verification is recorded separately from provenance availability.
  • Intended and observed deployment identities include timestamps and workload context.
  • Every final decision has an owner, raw-evidence links, and an expiry or reassessment trigger.

Pick the next finding that comes in. Run the manual record for one service, one finding, all six steps. If a second reviewer cannot reconstruct your decision from the raw evidence alone, it is not done.

Article series

From SBOM Findings to Defensible Decisions

Explore every resource in this series, whatever its format.

  1. articleWhy Your SBOM Does Not Protect You (and What Is Missing)
  2. articleFrom SBOM to Actionable Signal: Which Vulnerabilities Should You Actually Fix?
  3. guideBuilding a DevSecOps Evidence Chain: SBOM, Provenance, Deployment, and VEX
  4. articleResponding to a Critical CVE Without Triggering a Flood of False Positives
  5. articleVEX: Documenting "Not Exploitable" Without Turning Security into a Checkbox
  6. articleWhat the Cyber Resilience Act Changes for Software Vulnerability Management