Skip to content

fix(sbom): parse SPDX JSON format for LTS changelog card version chips#756

Merged
castrojo merged 1 commit into
projectbluefin:mainfrom
castrojo:fix/lts-sbom-spdx-parsing
Apr 14, 2026
Merged

fix(sbom): parse SPDX JSON format for LTS changelog card version chips#756
castrojo merged 1 commit into
projectbluefin:mainfrom
castrojo:fix/lts-sbom-spdx-parsing

Conversation

@castrojo
Copy link
Copy Markdown
Contributor

LTS SBOMs are published as spdx-json (the ISO/IEC 5962:2021 standard), while regular Bluefin uses syft-json (Syft-native/proprietary format). extractPackageVersions() only handled Syft JSON (artifacts[]), causing packageVersions to silently return null for every LTS release — so the changelog card at docs.projectbluefin.io showed no version chips (Kernel, GNOME, Mesa, Podman, bootc) for LTS releases.

Changes:

  • fetch-github-sbom.js: detect SPDX JSON via spdxVersion field, normalise packages[] filtered by pkg:rpm/ PURL into the same {name,version,type} shape that the existing RPM extraction loop expects
  • fetch-github-sbom.js: fix cache-hit logic for key-based (LTS/GDX) streams — attestation.verified is always false for these because verifyAttestation() uses OIDC keyless; treat populated packageVersions as a valid cache hit
  • fetch-github-sbom.js: update stale 'no SBOMs yet' comment for LTS/GDX
  • FirehoseFeed.tsx: update enrichLtsFromHistory comment to reflect that LTS does have an SBOM pipeline; the function is now a fallback for older releases

LTS SBOMs are published as spdx-json (the ISO/IEC 5962:2021 standard),
while regular Bluefin uses syft-json (Syft-native/proprietary format).
extractPackageVersions() only handled Syft JSON (artifacts[]), causing
packageVersions to silently return null for every LTS release — so the
changelog card at docs.projectbluefin.io showed no version chips
(Kernel, GNOME, Mesa, Podman, bootc) for LTS releases.

Changes:
- fetch-github-sbom.js: detect SPDX JSON via spdxVersion field, normalise
  packages[] filtered by pkg:rpm/ PURL into the same {name,version,type}
  shape that the existing RPM extraction loop expects
- fetch-github-sbom.js: fix cache-hit logic for key-based (LTS/GDX) streams
  — attestation.verified is always false for these because verifyAttestation()
  uses OIDC keyless; treat populated packageVersions as a valid cache hit
- fetch-github-sbom.js: update stale 'no SBOMs yet' comment for LTS/GDX
- FirehoseFeed.tsx: update enrichLtsFromHistory comment to reflect that LTS
  does have an SBOM pipeline; the function is now a fallback for older releases

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@castrojo castrojo merged commit cee4272 into projectbluefin:main Apr 14, 2026
1 check passed
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for SPDX-formatted SBOMs, specifically for LTS and GDX streams, allowing the extraction of RPM package versions from these sources. The update includes logic to detect the SBOM format and normalize data into a consistent structure, while also adjusting the cache hit criteria to accommodate key-based signing methods where OIDC verification is not applicable. A review comment suggests improving the robustness of the SPDX package mapping by using optional chaining to prevent potential runtime errors.

Comment on lines +712 to +725
artifacts = (sbom.packages || [])
.filter((pkg) => {
const refs = pkg?.externalRefs || [];
return refs.some(
(r) =>
r?.referenceCategory === "PACKAGE-MANAGER" &&
r?.referenceLocator?.startsWith("pkg:rpm/"),
);
})
.map((pkg) => ({
name: pkg.name,
version: pkg.versionInfo,
type: "rpm",
}));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The mapping logic for SPDX packages assumes that pkg is always an object. While the preceding filter uses optional chaining (pkg?.externalRefs), the map function directly accesses pkg.name and pkg.versionInfo. If the packages array contains null or undefined elements, this will throw a TypeError. Although the filter currently excludes such elements (because undefined?.externalRefs is falsy), it is safer and more robust to use optional chaining in the map as well, or ensure the filter explicitly removes non-object entries.

Suggested change
artifacts = (sbom.packages || [])
.filter((pkg) => {
const refs = pkg?.externalRefs || [];
return refs.some(
(r) =>
r?.referenceCategory === "PACKAGE-MANAGER" &&
r?.referenceLocator?.startsWith("pkg:rpm/"),
);
})
.map((pkg) => ({
name: pkg.name,
version: pkg.versionInfo,
type: "rpm",
}));
artifacts = (sbom.packages || [])
.filter((pkg) => {
const refs = pkg?.externalRefs || [];
return refs.some(
(r) =>
r?.referenceCategory === "PACKAGE-MANAGER" &&
r?.referenceLocator?.startsWith("pkg:rpm/"),
);
})
.map((pkg) => ({
name: pkg?.name,
version: pkg?.versionInfo,
type: "rpm",
}));

@castrojo castrojo deleted the fix/lts-sbom-spdx-parsing branch May 9, 2026 19:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant