Skip to content

A revised SBOM is indistinguishable from the original — but #20 argues against the fix #29

Description

@richardmhope

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.

The tension with #20

#20 says, explicitly:

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.

Decision needed

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions