To produce an SBOM for a release a customer still runs, go back to the exact inputs of that release: the signed tag, the lockfiles committed at that tag and, best of all, the archived image or binary the agency actually installed. Generate from the most complete input you still have, say plainly in the SBOM how and when it was made, then answer the vulnerability question for that version with a VEX statement rather than a sentence in an email.
This post is the working version for a platform engineer told: the agency runs 4.2, we ship 7.0, send the SBOM for exactly what they have, plus whether the new KEV entry touches it.
Key takeaways
- An SBOM for an old release is honest only when it names its own generation context. CISA's 2026 Minimum Elements add SBOM Generation Context, SBOM Tool Name, SBOM Tool Version and SBOM Timestamp, so a regenerated document should say "regenerated in October 2026 from the archived image", not pretend it was produced at build time two years ago.
- The best source, in order: the SBOM you archived at release time, the archived image or binary, the lockfiles at the release tag, and last of all a manifest without a lockfile. Each step down loses precision.
- Federal context: OMB M-26-05 (23 January 2026) rescinded M-22-18 and M-23-16 and lets agencies write contract terms that require a current SBOM on request. Your contract, not a government-wide form, is what you answer to.
- NIST SP 800-218 practice PS.3 asks you to archive each release (PS.3.1) and keep provenance data such as an SBOM for every component of each release (PS.3.2). That is the fix for next time.
- Answer "are we affected" for the exact version with a VEX status: not_affected (with a justification), affected, fixed or under_investigation.
- With Safeguard, SBOM generation and analysis in SPDX and CycloneDX is GA, the Safeguard CLI is GA, the Portal SBOM Repository with product versions and version comparison is GA, CSAF and VEX upload is GA, vulnerability management with CISA KEV and EPSS data and reachability analysis are GA, and attestation and signing is GA.
- No tool can recover a build you did not keep. If the image is gone and the lockfile was never committed, the SBOM you produce is a best reconstruction, and it must say so.
The situation
The request arrives through the contracting officer or the agency's security office. Version 4.2 sits in the agency's asset inventory, a vulnerability was just added to CISA's Known Exploited Vulnerabilities catalog, and they must decide how fast to act on every asset that might carry it. They need an SBOM for 4.2 and your statement on whether 4.2 is affected.
Your side looks different. Main is on 7.0. The 4.2 branch was cut two years ago, the release pipeline's owner has moved teams, and CI has been migrated since. Nobody is sure whether the release job produced an SBOM, or where it landed.
A bad week: someone scans main and sends it labelled "4.2". The agency's own scan of their image disagrees, and every later answer you give is checked twice.
A good week: you find the exact artifact the agency runs, generate the SBOM from it, label how it was made, check the KEV entry against it, and send the SBOM, a VEX statement and a one-page provenance note. Then you fix the release pipeline so the next request takes minutes.
The rules behind the request
This section summarises primary documents. It is not legal or contract advice. What you owe the agency is set by your contract, and agency requirements vary from one contract to the next.
OMB M-26-05: SBOMs on request, by contract
OMB Memorandum M-26-05, dated 23 January 2026, rescinded M-22-18 and its companion M-23-16. In their place it tells agencies to keep a complete inventory of software and hardware and to build assurance policies that match their own risk decisions. It says agencies may still use the secure software development resources created under M-22-18, such as the Secure Software Development Attestation Form, and that they may choose contract terms requiring a software producer to provide a current SBOM upon request. A footnote adds that for a cloud platform, such a term should require an SBOM of the runtime production environment.
So the obligation sits in your contract: read the clause before deciding what "current" means for a release the agency still runs. The memo also points agencies at NIST SP 800-218 and CISA's minimum elements work, which is what their reviewer will hold your SBOM against.
CISA's 2026 Minimum Elements for an SBOM
CISA published the 2026 Minimum Elements for a Software Bill of Materials on 29 July 2026, with co-authoring agencies from many countries. It replaces the 2021 NTIA minimum elements as the current baseline. Several of its data fields matter directly when you regenerate an SBOM for an old release:
| Element | What the 2026 document asks for | Why it matters for an old release |
|---|---|---|
| SBOM Author | The entity that created the SBOM data, not the tool | You, today, are the author, even if a different team built 4.2 |
| SBOM Timestamp | Date and time of the most recent update to the SBOM data, per RFC 9557 | Must be the regeneration date, not the release date |
| SBOM Generation Context | The lifecycle phase and data available when the SBOM was made, such as "before build", "build" or "after build" | Tells the reader whether you scanned source, a build log or the shipped artifact |
| SBOM Tool Name and SBOM Tool Version | The tool used to generate or amend the SBOM, and its version | A current tool on old inputs is a different claim from the original pipeline's tool |
| SBOM Version | A version for the SBOM document itself for each component name and version pair | Lets you issue 1.1 later when you correct it |
| SBOM Author Signature | A digital signature attributable to the SBOM author | Proves the document left you unmodified |
| Component Hash Value and Algorithm | A hash of the executable component artifact | If you no longer have the artifact, the document says the value is unknown |
The practices section matters just as much. Under "Frequency", each software version or update should have an associated SBOM, and a revised SBOM should be issued when new details are found or an error is corrected. Under "Accommodation of Updates to SBOM Data", authors should correct errors promptly. Under "Explicitly Identifying Unknown Information", if data for a field is missing, the author should state whether it is unknown or withheld. Under "Coverage", an SBOM should list all components including transitive dependencies, with no minimum depth, so that a recipient can conclude a new vulnerability does not affect them when the component is absent.
That last point is why the agency is asking: a complete SBOM lets them clear 4.2 on their own; an incomplete one's silence means nothing.
NIST SP 800-218, practice PS.3
The Secure Software Development Framework groups its release practices under PS, "Protect the Software". PS.3 is titled "Archive and Protect Each Software Release", and its purpose is to preserve releases so that vulnerabilities discovered after release can be identified, analysed and eliminated. That is precisely the situation you are in.
- PS.3.1 asks you to securely archive the files and supporting data for each release, such as integrity verification information and provenance data. NIST's examples include storing release files and associated images in repositories with read-only access for the people who need it, and protecting integrity data by keeping it separately or signing it.
- PS.3.2 asks you to collect, safeguard, maintain and share provenance data for all components of each release, with an SBOM given as the example. NIST's examples include making that data available to acquirers in standards-based formats, giving it to your own response teams, protecting its integrity with a way for recipients to verify it, and updating it whenever a component changes.
With PS.3 in place two years ago, this request would be a lookup. Without it, the steps below are how you recover.
CISA BOD 26-04 and the KEV catalog: why the agency is in a hurry
Binding Operational Directive 26-04, "Prioritizing Security Updates Based on Risk", was issued on 10 June 2026. It revokes BOD 19-02 and BOD 22-01. It applies to federal civilian agencies, not to you directly, but it explains the deadline pressure behind the email. Under BOD 26-04, how fast an agency must remediate is set by four variables: whether the asset is publicly exposed, whether the CVE is in CISA's Known Exploited Vulnerabilities catalog, whether an adversary can automate exploitation, and whether exploitation gives partial or total control. The directive's Table 1 maps those to remediation timelines.
A new KEV entry changes one of those inputs for every asset carrying the component. Your SBOM and VEX statement tell them whether 4.2 is one.
VEX: the format for "are we affected"
CISA's "Minimum Requirements for Vulnerability Exploitability eXchange (VEX)", published in April 2023, defines what a VEX statement must carry. Each statement gives exactly one status for the listed products against one vulnerability: "not_affected", "affected", "fixed" or "under_investigation". For not_affected, a justification should be given, chosen from a fixed list: component_not_present, vulnerable_code_not_present, vulnerable_code_not_in_execute_path, vulnerable_code_cannot_be_controlled_by_adversary or inline_mitigations_already_exist. If no justification is given, an impact statement explaining why must be provided instead.
VEX can be carried in more than one format. OASIS CSAF 2.0 defines a VEX profile (profile 5) in which product status groups such as known_affected, known_not_affected and fixed carry the answer. CycloneDX has its own VEX capability, and OpenVEX is a smaller standalone format. Ask the agency which one they ingest before you choose.
Step by step, with or without Safeguard
These steps use standard git, container and shell tooling.
1. Pin down exactly what the agency runs
"4.2" is not enough. Ask for, or find in your own delivery records, the most precise identifier available:
- the full version string, for example 4.2.0 or 4.2.3, including any hotfix suffix;
- for containers, the image digest, not the tag, because tags can be moved;
- for installed software, the installer file name and its checksum;
- for a hosted deployment you operate on their behalf, the deployment record for that environment.
An image digest is the strongest anchor: it identifies one exact image, and if your registry still holds it you can generate from the same bytes they run.
2. Inventory the inputs you still have
Before you generate anything, find out which of these still exist. This is the checklist to fill in.
| Input | Where to look | Have it? | Notes |
|---|---|---|---|
| SBOM produced at release time | Release assets, artifact store, CI artifacts, the release ticket | If yes, you may only need to re-send and re-check it | |
| Signed release tag | The git repository | Confirm the tag points at the commit you think it does | |
| Lockfiles at that tag | The repository at the tag | One per ecosystem and per service | |
| Archived container image by digest | Your registry, a backup bucket, a delivery mirror | Check retention policies before anything expires | |
| Shipped installer or binary | Release downloads, delivery portal, customer media | Hash it before you touch it | |
| Build logs for the release job | CI history | Often expired; check retention | |
| Base image digest used at build | Build logs, Dockerfile pin, image history | Tags such as a distro's "latest" do not count | |
| Vendored or copied code | The repository at the tag | Easy to miss in a manifest scan |
Each "no" becomes a line in your provenance note.
3. Freeze the evidence before you work on it
Before generating anything, take hashes of what you found, so you can show later that the SBOM describes those exact bytes.
# Confirm the tag and the commit it points at
git fetch --tags
git rev-parse v4.2.0^{commit}
git log -1 --format='%H %cI %an' v4.2.0
# Check the tag signature if your releases were signed
git tag -v v4.2.0
# Hash a shipped installer or archive before using it
sha256sum product-4.2.0-linux-amd64.tar.gz
# Record an image digest from your registry (example with docker)
docker pull registry.example.com/product@sha256:REPLACE_WITH_DIGEST
docker image inspect --format '{{index .RepoDigests 0}}' registry.example.com/product@sha256:REPLACE_WITH_DIGEST
Save these values next to the SBOM for the provenance note in step 7.
4. Choose the generation source and generate
Pick the best source you have; the next section explains the differences.
| You have | Generate from | Generation context to declare | Expected accuracy |
|---|---|---|---|
| The original release SBOM | Nothing; re-send it and re-check it | As originally declared | As good as it was then |
| The image by digest, or the shipped binary | The image or binary | After build | Best available; includes base image and OS packages |
| Lockfiles at the tag, but no image | A clean checkout of the tag | Before build | Good for application dependencies; misses base image, OS packages and anything added at build |
| Only manifests without lockfiles | A clean checkout of the tag | Before build, with stated uncertainty | Weak; resolved versions are guesses unless you reconstruct them carefully |
For a source checkout, use a separate worktree so you do not disturb your working copy:
git worktree add ../product-4.2.0 v4.2.0
cd ../product-4.2.0
git status --short # should print nothing
Run your SBOM generator against that directory, image or archive, and keep its version output for labelling.
5. Validate the document
Validate the SBOM against its format specification and check for the fields the agency's tooling reads: the top component with its exact version, a unique serial number or namespace, a timestamp, tool name and version, and package URLs or CPEs on every component.
6. Answer the vulnerability question for that exact version
Take the CVE from the KEV catalog and the affected version ranges from the advisory. Search the regenerated SBOM for the component by package URL, compare its version against the affected range, and decide the status:
- Component absent: not_affected, justification component_not_present.
- Component present, version outside the affected range: not_affected, with an impact statement naming the version found, or the vulnerable_code_not_present justification if the advisory supports it.
- Component present in the affected range: either affected, or not_affected with one of the code-level justifications if you can show it, for example the vulnerable function is never called in 4.2 (vulnerable_code_not_in_execute_path). Be conservative. A wrong not_affected is far worse for the agency than an honest affected.
- Not sure yet: under_investigation, with a date for the follow-up.
Write the answer as a VEX document in the agency's format, scoped to the exact version.
7. Write the provenance note
Attach a short note to the SBOM. The template below works as a starting point:
Product: Example Product
Release: 4.2.0 (git tag v4.2.0, commit REPLACE_WITH_SHA)
Artifact described: container image registry.example.com/product@sha256:REPLACE
SBOM author: Example Software, Inc. (platform engineering)
Generated: 2026-10-25T14:00:00Z (regenerated; no build-time SBOM was archived)
Generation context: after build (generated from the archived release image)
Tool: REPLACE_WITH_TOOL_NAME REPLACE_WITH_TOOL_VERSION
Format: CycloneDX 1.6 JSON (also available as SPDX 2.3 JSON)
SBOM version: 1 (first SBOM issued for this release)
Known gaps: component hashes unknown for vendored code under /third_party;
build-time-only tools are not listed
Signature: detached signature file product-4.2.0.cdx.json.sig
Contact: REPLACE_WITH_SECURITY_CONTACT
8. Sign, send, and record what you sent
Sign the SBOM and VEX document with your organisation's key, send them through the channel the contract names, and keep an exact copy with its hash and date. Corrections go out as a new SBOM version with a note on what changed.
Regenerating from a tag, a lockfile or an archived image
From the archived image or shipped binary (after build)
This is the closest you can get to "exactly what they have". The image contains the application, its resolved dependencies as installed, the language runtime, and the operating system packages from the base image. Scanning it gives an "after build" SBOM in CISA's terms and a "post-build" lifecycle in CycloneDX's terms.
Strengths: it reflects what was actually installed, carries real artifact hashes, and sees the base image's OS packages, where many KEV entries land. Weaknesses: binary analysis can miss statically linked, vendored or minified components, and a re-pushed tag may now point elsewhere, which is why you work from the digest.
From the lockfiles at the release tag (before build)
A lockfile pins each direct and transitive dependency to an exact version and, in most ecosystems, an integrity hash. Generated from a clean checkout of the tag, this gives a "before build" SBOM in CISA's terms and a "pre-build" lifecycle in CycloneDX's terms.
Strengths: precise for application dependencies and reproducible from git alone. Weaknesses: it knows nothing about the base image, OS packages, the runtime you shipped or files fetched during the build, and unpinned installs in a Dockerfile cannot be recovered from source. State whether development dependencies are included.
From manifests without lockfiles
A manifest says "any 2.x of this library". A generator either lists the range or resolves it against today's registry, which describes what would install now, not what shipped. If this is all you have, say so, list the declared ranges, and treat version-dependent answers as under_investigation.
Why the outputs differ, and what to send
| Difference | Image or binary | Lockfile at tag | Manifest only |
|---|---|---|---|
| OS and base image packages | Present | Absent | Absent |
| Language runtime version | Usually present | Absent unless declared | Absent |
| Transitive application dependencies | Present when metadata survives | Present and exact | Ranges or today's resolution |
| Build-time downloads | Present if they landed in the image | Absent | Absent |
| Vendored or copied code | Often missed | Missed unless declared | Missed |
| Component hashes of the shipped artifact | Available | Not for the artifact | Not available |
| CISA generation context | After build | Before build | Before build, with uncertainty |
If you have both, generate both and reconcile: packages in the lockfile but missing from the image are either pruned or a scanner miss. The live post on how to reconcile a source SBOM and an image SBOM for one release covers that comparison. Send the image SBOM as the primary document.
An illustrative worked example
The numbers here are invented and rounded, to show the shape of the result. Suppose 4.2.0 is a container image. A lockfile-based SBOM from the tag lists 600 application packages. The image-based SBOM lists 580 of those 600, plus 150 OS packages and the language runtime. The 20 missing application packages turn out to be development dependencies that the production build pruned. The KEV entry concerns an OS package. Only the image SBOM can answer the agency's question; the lockfile SBOM would have produced a confident and wrong "component not present".
How to label a regenerated SBOM honestly
A regenerated SBOM is legitimate; one dressed up as a build-time SBOM is not. The 2026 CISA elements give you the fields to tell them apart.
Use the format's own fields
In CycloneDX, the metadata object carries a timestamp for when the BOM was created, a tools list, authors, and a lifecycles array whose predefined phases include design, pre-build, build, post-build, operations and discovery. A unique serialNumber (a UUID URN) identifies the BOM, and the integer version should be incremented whenever an existing BOM is modified. For a regenerated SBOM from an archived image, set the timestamp to today, the lifecycle phase to post-build, the tool to the generator you actually ran, and the author to your organisation.
In SPDX, the document creation information carries the creators (including a "Tool:" entry with the tool name and version), the created timestamp, and a free-text creator comment. Use the comment to state that the document was regenerated, from what, and why.
Say what is unknown
The CISA 2026 document asks authors to explicitly state when information is unknown, and to distinguish unknown from withheld. In practice:
- If you generated from source and do not have the artifact, Component Hash Value for the shipped artifact is unknown. Say so rather than leaving it blank.
- If some components have no identifiable producer, mark them as unknown provenance, as the CISA text suggests.
- If you excluded build-time tools or test dependencies, state that in the note.
Keep the release identity separate from the SBOM identity
The component version is 4.2.0, what the agency runs. The SBOM version is the document's own version: 1 for the first one you issue for 4.2.0, incremented when you correct it.
A short labelling checklist
- Top component name and exact version match what the agency runs
- Timestamp is the regeneration time; generation context matches the source you scanned
- Tool name and tool version are the ones you actually ran; author is your organisation in full
- Unknown fields are marked unknown, not left empty; serial number or namespace is new
- The document validates, is signed by your organisation, and travels with a provenance note
Answering "are we affected" for that exact version
The SBOM answers "what is in 4.2". The VEX statement answers "does this KEV entry matter for 4.2". Keep them separate.
Match the advisory to the SBOM
Take the affected package identifiers and version ranges from the advisory and look for them in the 4.2 SBOM by package URL, since names collide across ecosystems. If the component appears more than once at different versions, check each instance; the CISA Coverage practice lists them separately for this reason.
Decide the status and write it down
Use the four VEX statuses and, for not_affected, one of the five justifications. Some patterns that come up often for old releases:
| What you find in 4.2 | VEX status | Justification or note |
|---|---|---|
| The vulnerable component is not in the SBOM | not_affected | component_not_present, valid only if your SBOM is complete for that layer |
| The component is present but at a version outside the affected range | not_affected | Give an impact statement naming the version found |
| The component is present and vulnerable, but the affected function is not used | not_affected | vulnerable_code_not_in_execute_path, with the evidence you used |
| The component is present and vulnerable, and the code path is reachable | affected | Add the action: upgrade path, backport plan or mitigation |
| The component is present and 4.2.x has a patched build | fixed | Name the exact fixed version, for example 4.2.4 |
| You do not know yet | under_investigation | Give a date for the next update |
Scope the statement to the version
Name 4.2.0 (or the exact patch level), not just the product. If 7.0 is fixed and 4.2 is affected, that is two statements. If you are deciding whether to keep patching the 4.x line at all, the post on when to end security backports for an old release line covers that decision.
What to archive per release from now on
This is PS.3.1 and PS.3.2 turned into a pipeline checklist. Add these as outputs of the release job, written to storage with retention that outlives your longest support commitment.
| Artifact | Why keep it | Where it comes from |
|---|---|---|
| The release image or binary, by digest | So you can rescan exactly what shipped | Release job push, with an immutable copy in long-retention storage |
| SBOM generated at build time, in the format your customers use | So the next request is a lookup | SBOM step in the release job |
| SBOM generated from the final artifact | Covers base image and OS packages | Scan of the pushed image |
| Lockfiles and build manifests at the tag | Lets you regenerate and reconcile | The git tag itself, plus a copy in the release bundle |
| Base image digest | Base image tags move | Build log or a pinned Dockerfile |
| Build provenance attestation | Shows which pipeline built which artifact from which commit | Attestation step in CI |
| Hashes of every shipped file | Integrity checks years later | Release job |
| Signatures over the SBOM and provenance | Lets recipients verify integrity, as PS.3.2 asks | Signing step |
| The vulnerability status at release | A baseline for "what changed since" | Vulnerability scan at release |
| The tool name and version used for each of the above | Needed for honest labelling | Release job log |
Check your registry's cleanup policies, which often delete old or untagged images, and keep release artifacts read-only as the PS.3.1 example suggests. Corrections are new document versions, never edits in place. The live post on how often to regenerate an SBOM covers the cadence side of this for current releases.
How Safeguard does this
Everything below comes from Safeguard's offering documentation and its public docs at docs.safeguard.sh. Where the docs do not show a screen or a command, this section describes the outcome instead of inventing one.
What you will use, with labels
| Capability | Label | Role in this job |
|---|---|---|
| SBOM generation and analysis (SPDX and CycloneDX) | GA | Generate the SBOM for the 4.2.0 tag or image |
| Safeguard CLI | GA | Scan a checkout, an image reference or an image archive from your own machine |
| Portal SBOM Repository with product versions and version comparison | GA | Keep each release's SBOM and diff 4.2.0 against 7.0 |
| Vulnerability management with CISA KEV and EPSS data | GA | Check findings for the 4.2.0 SBOM against KEV |
| CSAF and VEX upload | GA | Bring your VEX documents into the platform alongside the SBOM |
| Mitigations (risk acceptance, false positive, workaround, not applicable), scoped to one version | GA | Record the not_affected reasoning for 4.2.0 with approver and evidence |
| Attestation and signing | GA | Attest SBOMs and provenance for new releases from CI |
1. Install the CLI and sign in
The docs show the install and sign-in like this:
# Install the CLI
curl -fsSL https://cli.safeguard.sh/install | bash
# Sign in (OAuth 2.0 device-code flow; approve in the browser)
safeguard login
# On a machine without a browser
safeguard login --no-browser
2. Generate from the best source you have
The CLI's safeguard scan builds an SBOM for exactly one target, matches it against vulnerability databases and writes results as JSON files under the output folder. Pick the target that matches your decision from step 4 above.
From a clean checkout of the release tag (before build):
git worktree add ../product-4.2.0 v4.2.0
cd ../product-4.2.0
safeguard scan --dir . --output ../sbom-4.2.0-source
From the archived image in your registry (after build). The docs show private registry credentials passed as flags:
safeguard scan --image myregistry.azurecr.io/myapp:v1 \
--registry-username "$REGISTRY_USER" \
--registry-password "$REGISTRY_PASSWORD"
Use the digest form of the reference where you can, so you scan the exact image the agency runs.
From an image you saved to disk, the docs say safeguard scan --image also reads local images in the forms podman: plus a reference, docker-archive: plus a file, oci-archive: plus a file, and oci-dir: plus a directory. That matters for old releases, because the copy you kept in a backup bucket is usually a saved archive, not a live registry entry.
If you already have an old SBOM from the release, scan it rather than regenerating:
safeguard scan --sbom sbom.json
Results land as JSON files such as vuln.json and license.json. For scripts, the docs say safeguard scan does not fail on findings, and it uses a separate exit code when results were written but the vulnerability scan did not run, so a skipped scan never looks like a clean pass.
3. Get the result into the platform
The docs say that scanning from the interactive terminal while signed in uploads the SBOM and findings to the platform, and that your source never leaves the machine:
safeguard
# then, inside the terminal:
/login
/scan .
Run this from the 4.2.0 worktree so the uploaded project reflects that release. For repositories connected through the platform instead, the docs describe an Integrations page where each connected repository has a Branch/Tag setting and a Version setting (Version defaults to 1.0.0, and the generation options say the version can be auto-detected from git tags). Set Branch/Tag to the release tag and Version to 4.2.0.
4. Validate the SBOM before it leaves
The docs show a validate command that checks CycloneDX (JSON and XML), SPDX (JSON, YAML, tag-value and RDF) and VEX documents (CSAF and OpenVEX) against their specifications:
safeguard validate sbom.json --strict -o report.json
Run it on the SBOM and the VEX document before sending either. Validation proves the document is well formed, not that it is complete.
5. File the SBOM under the product and version in the Portal SBOM Repository
The Portal (here meaning the SBOM publish and share product, not the free entry tier) has an SBOM Repository organised by product, version and tag. The docs describe the in-app flow:
- Go to Products and click Create Product, entering the product name, SKU and description, if the product does not exist yet.
- Click Import SBOM, select the format (SPDX, CycloneDX and others), upload the file or paste its content, and assign it to the product and version.
- Or let SBOMs from the scanning side sync automatically: Settings, then Integrations, then enable the sync and pick projects and frequency.
Each SBOM record shows its product, version, original format, component count, created date, source and an EO 14028 compliance status. Add custom tags such as the contract or "regenerated".
The offering documentation draws a distinction worth keeping straight here: publishing moves an artifact into the Portal as an immutable copy, while sharing sends it onward as is (by direct link, branded customer portal or NDA-gated access, tracked, with audit trails). The immutable copy is your record of exactly what you sent.
6. Compare 4.2.0 with 7.0
The Version Comparison feature in the SBOM Repository takes two versions of the same product. Select both and click Compare. The docs list what you see: added components, removed components, version changes, new vulnerabilities and resolved vulnerabilities.
It shows quickly whether the KEV component changed between 4.2.0 and 7.0, and it gives you a component-level case for moving the agency to a current release.
7. Check the KEV entry against the 4.2.0 findings
Safeguard's vulnerability management matches components against sources including NVD, GitHub security advisories, OSV, CISA KEV and vendor bulletins, with EPSS alongside. Find the CVE in the 4.2.0 findings and check the component and version. If it is present, reachability analysis (GA) helps you judge whether the vulnerable path is used, the evidence a vulnerable_code_not_in_execute_path justification needs. It informs your judgment; it does not replace it.
8. Record the decision as a mitigation scoped to this version
If the answer for 4.2.0 is not_affected, record why. The Mitigations tab on a project lets you add a mitigation from a vulnerability with a type (risk acceptance, false positive, workaround or not applicable), a required justification, a required "approved by", optional evidence, and a required scope of "this version only" or "all versions". For an old release, choose this version only, because the same reasoning may not hold for 7.0.
Each mitigation keeps a status and a history of who changed what, and Reports, then Mitigations, exports them as PDF, CSV or Excel for when someone later asks why you said not_affected.
9. Upload the VEX document
Safeguard's CSAF and VEX upload is available from Integrations as a file upload ("Upload CSAF/VEX" in the docs). Upload the VEX statement you wrote for 4.2.0 so it sits with the SBOM and findings for that release. The VEX document itself is still yours to author and sign; the docs reviewed for this post describe upload and analysis, not generating VEX on your behalf.
10. Attest new releases so this never happens again
For releases from now on, the docs describe a CI step that produces signed attestations in in-toto format, including SLSA provenance, a CycloneDX SBOM and a vulnerability scan snapshot:
- name: Attest build
uses: safeguard/attest@v2
with:
artifact: ./dist/app.tar.gz
predicates:
- slsa-provenance
- sbom-cyclonedx
- vuln-scan
The docs say attestations are signed with Safeguard's own key and verified against its published public key, and that there is no CLI command for signing yet, so this happens in CI. With continuous scanning on push, on a schedule or on release, this covers much of the PS.3 checklist above for future releases. For the agency conversation about build provenance specifically, see how to show SLSA build provenance to a federal agency customer.
What Safeguard does not do
- It cannot recover a build you did not keep. If the 4.2.0 image was deleted and no installer survives, Safeguard can only generate from the tag and lockfiles, which is a "before build" SBOM without the base image or OS packages. The regenerated SBOM is only as accurate as the archived inputs, and no tool changes that.
- It cannot rebuild a binary faithfully from old source. A two-year-old build re-run today pulls today's unpinned inputs. Safeguard scans what exists; it does not make a build reproducible.
- It does not write your provenance note or decide your VEX status. Reachability analysis and findings are inputs. Choosing not_affected for a federal customer, and standing behind it, is your call and your signature.
- Attestations it makes now do not prove what happened then. An attestation produced today over a regenerated SBOM attests to that SBOM, made today. It does not show which pipeline built 4.2.0 two years ago.
- Its signatures use Safeguard's key. The docs say attestations are signed with Safeguard's own key. If your contract or the CISA SBOM Author Signature element calls for a signature attributable to your company, sign the documents you send with your own organisation's key as well.
- It does not interpret your contract. Agency requirements vary by contract. The Portal shows an EO 14028 status per SBOM record; whether a document meets your contract's clause or the 2026 CISA elements is yours to check.
- It is not a federal authorization. Safeguard is designed for FedRAMP High, which is an architecture target, and its SOC 2 Type II audit is in progress. Neither substitutes for the authorizations your own contract requires of you.
- The documented REST endpoints for the SBOM Repository and Mitigations are not available yet. Those docs pages carry a banner saying the
/v1paths return 404 today. Use the CLI, the interactive terminal and the in-app flows described above.
Common mistakes
- Scanning main and calling it 4.2. The most common and most damaging error. If you cannot check out the tag or get the artifact, say so.
- Using the image tag instead of the digest. Tags move. Two years of re-pushes later, the tag may point at a patched rebuild, and your SBOM will describe something the agency does not run.
- Back-dating the timestamp. The SBOM Timestamp element is when the SBOM data was last updated. Setting it to the release date makes the document misleading, and a reviewer comparing tool versions will notice.
- Claiming component_not_present from a lockfile SBOM for an OS-level CVE. The lockfile SBOM cannot see OS packages. Only claim absence for layers your SBOM covers.
- Resolving manifest ranges against today's registry. That yields what would be installed today, not what shipped.
- One VEX statement for every version. Scope each statement to the product version you checked.
- Editing the archived SBOM in place. Issue a new SBOM version with a note on what changed, as the CISA update practice expects.
FAQ
How do I produce an SBOM for an old release a customer still runs?
Find the exact artifact they run (ideally an image digest or installer checksum), generate the SBOM from that artifact, and fall back to a clean checkout of the release tag with its lockfiles only if the artifact is gone. Label the document with the regeneration date, tool, tool version and generation context, mark unknown fields as unknown, sign it, and attach a short provenance note.
Is a regenerated SBOM acceptable to a federal agency?
It depends on your contract, which is what OMB M-26-05 points agencies to. The CISA 2026 Minimum Elements expect an SBOM per version and allow revised SBOMs as new information appears, so a clearly labelled regenerated SBOM fits that model. A regenerated SBOM presented as if it were made at build time does not.
What generation context should I declare for an SBOM made from an archived container image?
CISA's 2026 elements give "after build" as the general reference for SBOMs made from built artifacts, and CycloneDX calls the same phase "post-build". Declare that, and name the image digest you scanned.
Why does my SBOM from the git tag differ from the agency's scan of the image?
A tag and lockfile scan sees application dependencies only. The image adds the base image, operating system packages, the language runtime and anything fetched during the build. Generate from the image if you can, and reconcile the two if you have both.
What if the lockfile was never committed for that release?
Then the SBOM from source can only list declared ranges, not resolved versions. Say that in the note, avoid resolving ranges against today's registry, and mark vulnerability answers that depend on exact versions as under investigation until you can confirm against an artifact.
How do I tell the agency whether a new KEV entry affects version 4.2?
Check the vulnerable component and affected version range from the advisory against the 4.2 SBOM, then send a VEX statement scoped to 4.2 with one of four statuses: not_affected (with a justification), affected, fixed or under_investigation.
What should we archive for every release from now on?
The artifact by digest, a build-time SBOM and an artifact SBOM, lockfiles, the base image digest, a provenance attestation, hashes, signatures and the vulnerability status at release, in read-only storage that outlives your support commitment. That is SSDF PS.3.1 and PS.3.2 in practice.
Does CISA BOD 26-04 apply to software vendors?
No. BOD 26-04 binds federal civilian agencies. It matters to you because it sets how quickly agencies must act on vulnerabilities, using KEV status as one of four factors, which is why they want your answer fast.
Answering the agency tells them whether 4.2 carries the vulnerable component; it does not move a fix into the 4.x line. If the answer is affected and you still support that line, the options below are how a fix reaches the release branch without waiting on someone else's schedule.
Fix it without waiting for upstream
Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.
1. Autonomous remediation: pull requests, not tickets
When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation categories include dependencies, licenses, security posture and findings, and each one is set separately. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.
2. Gold Open Source: the safe version in seconds, free
gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds.
3. Gold Registry: start from components that are already fixed
Gold Registry provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs and a completed license check, with signed build provenance (signed with Safeguard's key and verifiable with cosign, SLSA Build Level 3 as the design target) and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.
When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. Ask which packages it covers before you plan around it.
| Your situation | What to use |
|---|---|
| A fixed version exists | Autonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version |
| You need to know today whether you are affected | Gold Open Source lookup and "Am I affected?" checker, free and without login |
| You want vulnerable versions to stop shipping | Safeguard policies and gates in CI |
| Upstream has no fix yet, or will not ship one | A custom Gold request; fork and patch |
| You want to start clean on new projects | Pull hardened components and images from Gold Registry |
One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.
See how Safeguard would help
The first demo is a real CLI session: install, open the terminal with safeguard, ask it to fix the lodash CVE in a repository, and watch it read the finding and advisory, ask before any command that changes something, edit package.json to lodash 4.17.21, run npm install and npm test with approval, print a summary and push nothing; then /permissions, /model and /scan. The same terminal and /scan . are what you run from a 4.2.0 worktree to upload that release's SBOM and findings.
Click through it at your own pace, or open it full screen.
The second demo sets up the local runner on your own machine, approves it with its device code, and then scans from the terminal. For an old release this is the practical path when the archived image or the release checkout lives on an internal machine or a backup host you do not want to expose, because the scan runs where the files are.
Click through it at your own pace, or open it full screen.
To try it on your own release archive, download Safeguard from https://safeguard.sh/download and follow the docs at https://docs.safeguard.sh/docs .
Quick check
You only have the git tag and lockfiles for 4.2, and the KEV entry is in an operating system package. Can you send "not_affected, component_not_present"?
No. An SBOM made from lockfiles does not see the base image or operating system packages, so its silence about that package proves nothing. Find the archived image or installer and generate from it, or send under_investigation until you can.
What timestamp belongs on an SBOM you regenerate today for a release from two years ago?
Today's date and time. The CISA 2026 SBOM Timestamp element records when the SBOM data was last updated, not when the software was released. Put the release identity in the component version and the provenance note instead.
Sources
- CISA, 2026 Minimum Elements for a Software Bill of Materials (SBOM), PDF
- CISA, 2026 Minimum Elements for an SBOM, resource page
- OMB Memorandum M-26-05, Adopting a Risk-based Approach to Software and Hardware Security
- NIST SP 800-218, Secure Software Development Framework version 1.1
- CISA, BOD 26-04: Prioritizing Security Updates Based on Risk
- CISA, Known Exploited Vulnerabilities Catalog
- CISA, Minimum Requirements for Vulnerability Exploitability eXchange (VEX), PDF
- OASIS, Common Security Advisory Framework Version 2.0
- CycloneDX 1.6 JSON reference
- SPDX 2.3, Document Creation Information
- OpenVEX specification
- Safeguard docs, Generate SBOM
- Safeguard docs, SBOM Repository
- Safeguard docs, CLI Usage
- Safeguard docs, Mitigations
- Safeguard docs, Attestation and Signing
Last reviewed: 25 October 2026. Product capabilities change; check docs.safeguard.sh for the current state.