feat(sbom): consistent primary component, document identity, and CRA metadata - #364
feat(sbom): consistent primary component, document identity, and CRA metadata#364bomly-guy wants to merge 1 commit into
Conversation
…metadata Improve SBOM export quality based on third-party validator findings (sbom-tools v0.1.22 reported grade F / 43.4 overall on our own scan): - Primary component: synthesize a project root (application type, pkg:generic PURL) when the graph has multiple roots, instead of letting CycloneDX metadata.component fall to an arbitrary manifest node (previously a .github workflow file). The root depends on every graph root, so the exported dependency graph is one connected component, and both formats now name the same scanned project (cross-format component identity: 0 added / 0 removed in sbom-tools diff). Single-root graphs keep their natural root. Re-ingestion skips the pseudo root. - Document identity: generate a UUIDv4 per export; CycloneDX gets a urn:uuid serialNumber and the SPDX namespace reuses the same nonce. - Tool version: emit bomly's version in CycloneDX metadata.tools and as the SPDX "bomly-cli-<version>" tool creator. - Component hashes: project detection-time dependency digests (npm SRI integrity, nuget, cocoapods) into SBOM components, normalized to lowercase hex; parse go.sum h1 tree hashes in the gomod detector and expose them as sha256 (cyclonedx-gomod convention). 89% of components in a self-scan now carry hashes (was 0%). - CRA readiness: optional sbom config section (manufacturer, security_contact, vulnerability_disclosure_url, support_end) emitted as CycloneDX metadata.manufacturer, security-contact/advisories external references, and a support-end property; SPDX gets an Organization creator, root package supplier, and creation-info comment. Self-scan score moves 43.4 (F) to 59.4 with no config and to fully recognized manufacturer/contact/support fields with the sbom section set. NTIA minimum elements remain compliant for both formats; both outputs validate clean against the official CycloneDX 1.7 and SPDX 2.3 schemas. The 3 cycles the validator reported are real Go module-graph cycles (otel, grpc/xds, cloud auth), not export artifacts. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Warning Review limit reached
Next review available in: 38 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (15)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Bomly Diff SummaryCompared Overview
Dependency Changes✅ No dependency changes. Vulnerabilities✅ No vulnerability changes. License Changes✅ No license changes. Project Posture✅ No project posture changes ( Policy Findings✅ No policy differences were identified. |
Summary
Improves SBOM export quality based on findings from running
sbom-toolsv0.1.22 againstbomly scan -o cyclonedx -o spdxoutput of this repo (baseline: grade F, 43.4 overall). Self-scan now scores 59.4 with zero config, with the remaining CRA errors being data we refuse to invent (see "Deliberate non-fixes").1. Primary component identity (finding 1)
metadata.componentpreviously fell toRoots[0]— an arbitrary manifest node (.github/workflows/auto-version.yml). When a graph has multiple roots,sbom.FromDepGraphnow synthesizes a project root: named after the scanned project,applicationtype,pkg:genericPURL, depending on every graph root. Both formats now agree on the document's subject (sbom-tools cross-format diff: 0 added / 0 removed components, was 44.7% similarity with full mismatch), and the exported graph is one connected component (islands 3 → 1, orphans 1 → 0, roots 14 → 1). Single-root graphs keep their natural root. The pseudo root is excluded from the CycloneDX component inventory and skipped on re-ingestion (round-trip verified).2. Serial number (finding 2)
Each export generates a UUIDv4: CycloneDX
serialNumber(urn:uuid:…), and the SPDX document namespace reuses the same nonce (https://bomly.dev/spdx/<uuid>), so the two exports of one scan are correlatable.3. Tool version (finding 3)
CycloneDX
metadata.tools[]now carries bomly's version; SPDX emitsCreator: Tool: bomly-cli-<version>(SPDX 2.3toolidentifier-versionconvention, same as syft/trivy). Note: sbom-tools' SPDX parser doesn't recognize the hyphen convention (onlyname vX/name (X)/name@X), sohas_tool_versionstays false on the SPDX side — checker quirk, not missing data.4. Component hashes (finding 4)
go.sumand attachesh1:tree hashes as sha256 (hex), matching cyclonedx-gomod's convention. Self-scan: 89% of components carry hashes (was 0%).supplieranddescriptionare not cheaply fillable without enrichment data sources that provide them; we don't fabricate them to satisfy profile checkers. Licenses without--enrichremain empty as expected.5. Dependency graph verification (finding 5)
The CDX
dependenciessection was already complete: all 343 components have an entry; "188/344 with edges" is simply the non-leaf count. The 3 reported cycles are real Go module-graph cycles (go.opentelemetry.io/otel*,grpc/envoyproxy/cncf-xds,cloud.google.com/go/auth*) — module-level cycles are legitimate in Go, not export artifacts. The islands/orphan were the disconnected manifest roots, fixed by the synthesized project root. The residual cross-format semantic-similarity gap (~44%) is an sbom-tools comparator artifact: it derives CDX edge scope from component scope and has no SPDX equivalent (verified: stripping scope from our CDX yields 99.97% similarity; scoped SPDX relationship types don't map either). We keep scope data rather than degrade the export.6. CRA-readiness metadata (finding 6)
New optional
sbom:config section (config file + env vars, no new CLI flags):CycloneDX:
metadata.manufacturer,security-contact/advisoriesexternal refs on the primary component,bomly:support_end_dateproperty. SPDX:Organizationcreator, primary-package supplier, creation-info comment. All four verified recognized by sbom-tools' CRA profile.support_endis validated as an ISO date.Validation
make test,make lint,make generateall clean.--sbomscans of our own exports) produces identical dependency counts, with the pseudo root correctly excluded.Notes for reviewers
SBOM interoperability assuranceworkflow (linux-only validators) should be dispatched on this branch or after merge for the external-validator pass.🤖 Generated with Claude Code