You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Raising this as a decision to make, not a change to apply, because the obvious fix contradicts a decision already recorded in #20.
From the assessment against CISA's 2026 Minimum Elements (docs/cisa-sbom-minimum-elements-2026.md on branch claude/tool-sbom-requirements-assessment-jkudvt). One of that guidance's practices is Accommodation of Updates to SBOM Data — an SBOM must be revisable, which means a consumer needs to be able to tell one revision from another and know which supersedes which.
What we emit
src/icebergsca/report/cyclonedx.py:60-64 hardcodes "version": 1 and emits no serialNumber. CycloneDX defines serialNumber as the document's identity (tests/schemas/bom-1.6.schema.json:30) and version as its revision number.
So every SBOM we produce is revision 1 of an unnamed document. Regenerate after fixing a parse failure, or after a dependency bump, and the new document is indistinguishable from the old except by content diff — and per #20 the content diff is unusable anyway, because the timestamp changes every run.
Worth noting what is already right: we emit no CycloneDX serialNumber, which would otherwise be a random UUID with exactly the same problem. That omission should be treated as deliberate and kept.
That is correct on its own terms. A random UUID per run defeats digest-based attestation exactly as the wall-clock timestamp does. The two requirements pull in opposite directions:
Reproducibility wants byte-identical output for identical input, so an SBOM can be an attestation predicate and so "did this change?" is answerable.
Revisability wants stable document identity plus a monotonic revision number, so a consumer can order two SBOMs of the same product.
Both are legitimate. They are not actually incompatible — what is incompatible is randomness, not identity.
The resolution I would propose
A serialNumber that is derived rather than generated:
a UUIDv5 over a stable key — the project identity plus source ref from The SBOM does not say which source it describes #21, or a digest of the parsed inputs — so the same project produces the same serial on every run, and a different project a different one;
version incremented only when the caller says so, via a --bom-version flag, since the tool is stateless and cannot know it is producing a revision of anything;
--serial-number to override outright, for callers that track SBOM identity themselves.
That satisfies revisability without reintroducing per-run churn, and it keeps #20's reproducibility guarantee intact. It does mean #20's instruction ("keep the omission") needs amending rather than following, which is why this is an issue and not a patch.
Note the ordering dependency: a derived serial needs something stable to derive from, and that is exactly what #21 adds. #20 → #21 → this is the natural sequence, and doing this one first would mean deriving identity from the scanned directory's basename, which is the very weakness #21 exists to fix.
If the answer is "caller's job", that is a perfectly good outcome — but it should be written down as a deliberate limitation rather than left as a field nobody considered, and the docs should say how a caller is expected to handle it.
Raising this as a decision to make, not a change to apply, because the obvious fix contradicts a decision already recorded in #20.
From the assessment against CISA's 2026 Minimum Elements (
docs/cisa-sbom-minimum-elements-2026.mdon branchclaude/tool-sbom-requirements-assessment-jkudvt). One of that guidance's practices is Accommodation of Updates to SBOM Data — an SBOM must be revisable, which means a consumer needs to be able to tell one revision from another and know which supersedes which.What we emit
src/icebergsca/report/cyclonedx.py:60-64hardcodes"version": 1and emits noserialNumber. CycloneDX definesserialNumberas the document's identity (tests/schemas/bom-1.6.schema.json:30) andversionas its revision number.So every SBOM we produce is revision 1 of an unnamed document. Regenerate after fixing a parse failure, or after a dependency bump, and the new document is indistinguishable from the old except by content diff — and per #20 the content diff is unusable anyway, because the timestamp changes every run.
The tension with #20
#20 says, explicitly:
That is correct on its own terms. A random UUID per run defeats digest-based attestation exactly as the wall-clock timestamp does. The two requirements pull in opposite directions:
Both are legitimate. They are not actually incompatible — what is incompatible is randomness, not identity.
The resolution I would propose
A
serialNumberthat is derived rather than generated:versionincremented only when the caller says so, via a--bom-versionflag, since the tool is stateless and cannot know it is producing a revision of anything;--serial-numberto override outright, for callers that track SBOM identity themselves.That satisfies revisability without reintroducing per-run churn, and it keeps #20's reproducibility guarantee intact. It does mean #20's instruction ("keep the omission") needs amending rather than following, which is why this is an issue and not a patch.
Note the ordering dependency: a derived serial needs something stable to derive from, and that is exactly what #21 adds. #20 → #21 → this is the natural sequence, and doing this one first would mean deriving identity from the scanned directory's basename, which is the very weakness #21 exists to fix.
Decision needed
serialNumber, or caller-supplied only?versionstay hardcoded, or become a flag?cyclonedx.pynext to the decision, and amend Deterministic output, so an SBOM can be attested by digest #20's note so the two do not contradict each otherIf the answer is "caller's job", that is a perfectly good outcome — but it should be written down as a deliberate limitation rather than left as a field nobody considered, and the docs should say how a caller is expected to handle it.