Skip to content

Make CBOM output conform to the CycloneDX 1.6 schema - #2

Merged
thebenignhacker merged 1 commit into
mainfrom
fix/cyclonedx-schema-compliance
Jul 27, 2026
Merged

Make CBOM output conform to the CycloneDX 1.6 schema#2
thebenignhacker merged 1 commit into
mainfrom
fix/cyclonedx-schema-compliance

Conversation

@thebenignhacker

Copy link
Copy Markdown
Member

Fixes #1.

@ShivCod was right on both points. Validated against the official
bom-1.6.schema.json, the CBOM this tool emitted failed on three counts, so no
document it produced would pass the CycloneDX CLI.

Before

crypto-samples CBOM: 3 schema violations
  - serialNumber: "urn:uuid:20260727-132059-000000000" does not match
    "^urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
  - components/14/.../primitive: "hybrid" is not one of [... "combiner" ...]
  - components/20/.../primitive: "hybrid" is not one of [... "combiner" ...]

After

crypto-samples CBOM: 0 schema violations
PEM key material CBOM: 0 schema violations

Schema mapping deficiencies (your point 2)

  • serialNumber was time.Now().Format("20060102-150405-000000000"). That is a
    timestamp, not a UUID. Now a random RFC 4122 version 4 UUID.
  • primitive returned "hybrid" and "key-agreement", neither of which is in
    the spec enum. CycloneDX spells these combiner and key-agree. A single
    non-member value invalidates the entire document, which is why this affected
    every scan rather than only hybrid ones.
  • The hybrid case now also runs before the post-quantum cases, so a hybrid
    ML-KEM construction reports as the combiner it is instead of a plain kem.

Incomplete key material representation (your point 1)

categoryToAssetType matched lowercase category names that no pattern actually
uses. The real categories are "Secret Detection" and "Certificate", so every
finding fell through to the default and was emitted as an algorithm. Your
-----BEGIN RSA PRIVATE KEY----- became:

{ "name": "Private Key Header", "cryptoProperties": { "assetType": "algorithm" } }

losing the fact that it was key material at all. Now:

{
  "name": "Private Key Header",
  "cryptoProperties": {
    "assetType": "related-crypto-material",
    "relatedCryptoMaterialProperties": { "type": "private-key" }
  }
}

Certificates and CSRs were affected by the same case-matching bug and are now
classified correctly too.

Also fixed

Evidence locations were absolute paths, embedding the scanning machine's
directory layout and username into an artifact meant to be committed and shared
with auditors, and making identical scans of the same source differ between
machines and CI runners. They are now relative to the scan root.

Testing

New tests assert the serial number pattern and uniqueness, every emitted
primitive and assetType against the spec enums, key material classification,
and path relativization.

Two existing tests asserted the invalid values ("key-agreement", and key
mapping to certificate) and were updated. They were encoding output the spec
rejects, and a key is not a certificate.

Validated against the official bom-1.6.schema.json, the emitted CBOM failed on
three counts, so no document this tool produced passed the CycloneDX CLI.

serialNumber was built with time.Now().Format("20060102-150405-000000000").
That is a timestamp, not a UUID, and it does not match the required
urn:uuid pattern. Replaced with a random RFC 4122 version 4 UUID.

algorithmToPrimitive returned "hybrid" for hybrid constructions and
"key-agreement" for key agreement. Neither is a member of the spec's closed
primitive enum, and one non-member value invalidates the whole document.
CycloneDX spells these "combiner" and "key-agree". The hybrid case now also
precedes the post-quantum cases so a hybrid ML-KEM construction is reported as
the combiner it is rather than as a plain KEM.

categoryToAssetType matched lowercase category names that no pattern actually
uses. The real categories are "Secret Detection" and "Certificate", so every
finding fell through to the default and was emitted as an algorithm. A detected
private key became assetType "algorithm" named "Private Key Header", which is
the incomplete key material representation described in the report. Key material
is now emitted as related-crypto-material carrying its material type and size.

Evidence locations were absolute paths, embedding the scanning machine's
directory layout and username into an artifact meant to be committed and shared,
and making identical scans differ between machines. They are now relative to the
scan root, falling back to the original path when no relative path exists.

Two existing tests asserted the invalid values ("key-agreement" and key mapping
to certificate) and were updated, since they locked in output the spec rejects.

Fixes #1
@thebenignhacker
thebenignhacker merged commit 86a9dd0 into main Jul 27, 2026
4 checks passed
@thebenignhacker
thebenignhacker deleted the fix/cyclonedx-schema-compliance branch July 27, 2026 20:05
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.

CBOM Output Non-Compliance with CycloneDX Schema

1 participant