Skip to content

CBOM Output Non-Compliance with CycloneDX Schema #1

Description

@ShivCod

The matcher correctly identifies PEM-encoded cryptographic material, including:

  • -----BEGIN RSA PRIVATE KEY-----
  • -----BEGIN EC PRIVATE KEY-----
  • -----BEGIN OPENSSH PRIVATE KEY-----
  • -----BEGIN CERTIFICATE REQUEST-----

However, the CBOM JSON output produced does not conform to the official CycloneDX specification (https://cyclonedx.org). Two specific gaps have been identified:

  1. Incomplete key material representation – The full cryptographic asset details are not preserved in the output.
  2. Schema mapping deficiencies – The generated JSON fails validation when checked against the CycloneDX CLI, due to incomplete field mappings.

Activity

  1. thebenignhacker commented on Jul 27, 2026

    @thebenignhacker
    Member

    Thank you for this, and apologies for the long silence.

    You were right on both points, and I could reproduce both. Validating our output
    against the official bom-1.6.schema.json showed three violations, so no CBOM
    this tool produced would have passed the CycloneDX CLI:

      - serialNumber: "urn:uuid:20260727-132059-000000000" does not match the
        required urn:uuid pattern
      - components/14/.../primitive: "hybrid" is not one of the permitted values
      - components/20/.../primitive: "hybrid" is not one of the permitted values
    

    Schema mapping deficiencies. The serial number was a formatted timestamp
    rather than a UUID. Separately, primitive emitted "hybrid" and
    "key-agreement", neither of which is in the spec enum. CycloneDX spells those
    combiner and key-agree. Because a single non-member value invalidates the
    whole document, this affected every scan, not only ones involving hybrids.

    Incomplete key material representation. The root cause was narrower than it
    looked. categoryToAssetType matched lowercase category names that no pattern
    in the codebase 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 a component named
    "Private Key Header" with assetType: algorithm, which lost the fact that it
    was key material at all. It now emits as:

    {
      "assetType": "related-crypto-material",
      "relatedCryptoMaterialProperties": { "type": "private-key" }
    }

    Certificates and CSRs were hitting the same case-matching bug and are classified
    correctly now as well.

    Fix is in #2. Both the sample corpus and a PEM key fixture now validate with 0
    violations against the official schema, and there are tests asserting every
    emitted primitive and assetType against the spec enums so this cannot drift
    back silently.

    One extra fix in the same PR: evidence locations were absolute paths, which put
    the scanning machine's directory layout and username into an artifact meant to
    be shared. Those are now relative to the scan root.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions