Skip to content

[2.0] fixes on schema and test resources - #1001

Merged
jkowalleck merged 48 commits into
2.0-devfrom
2.0-tests-init-fixes
Aug 24, 2026
Merged

[2.0] fixes on schema and test resources#1001
jkowalleck merged 48 commits into
2.0-devfrom
2.0-tests-init-fixes

Conversation

@jkowalleck

@jkowalleck jkowalleck commented Aug 4, 2026

Copy link
Copy Markdown
Member

fixes or related to

see also:

besides those fixes above, this is in the PR:

  • made the refLinkType inherit explicit
  • fixes the array nesting of extensibleProerties
  • consolidated milisecond timestamp for JSS
  • adds $comments
  • enhanced some docs
  • added test cases
    • for extensibleProperties
  • fixed valid test data
    • all test data that was just carried over from CDX 1.x was transferred to CDX 2.0schema
  • fixed invalid test data
    • removed invalid-component-choice-missing-name-2.0.json - as the name was optional or did not exist.
      ❓ was this intentional/correct

tests for the things are based on:

@jkowalleck jkowalleck mentioned this pull request Aug 4, 2026
4 tasks
@jkowalleck jkowalleck changed the title 2.0 tests init fixes 2.0 fixes Aug 4, 2026
@jkowalleck jkowalleck added defect CDX 2.0 related to release v2.0 labels Aug 4, 2026
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
@jkowalleck
jkowalleck force-pushed the 2.0-tests-init-fixes branch from a03e560 to 905e58a Compare August 4, 2026 15:36
jkowalleck added a commit that referenced this pull request Aug 4, 2026
- [x] Java tests - functional
- [x] JS tests - functional - WIP
- found some false-positives/false-negatives - due to errors in test
resources
- [x] JS tests - schema validate
  - includes #996
  - includes #992
- JS tests - semantics
  - [x] #998
  - [x] #995
- [x] PHP tests - functional

added tests only,
no schema/res fixes - they are prepared in 
- #997 
- #1001

---------

Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
jkowalleck and others added 23 commits August 4, 2026 19:00
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed the test case, since the name was not required at all ...

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was intended, agreed by @stevespringett

Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
@jkowalleck
jkowalleck marked this pull request as draft August 21, 2026 13:30
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
@jkowalleck

jkowalleck commented Aug 21, 2026

Copy link
Copy Markdown
Member Author

had Fable 5 analyze the state of the schema.

my query:

Analyze the JSON Schema structure under https://github.com/CycloneDX/specification/blob/2.0-tests-init-fixes/schema/2.0/cyclonedx-2.0.schema.json . Ignore all `-bundled` files.

Starting from the root schema , follow every $ref transitively through the files in  (e.g. cyclonedx-metadata, cyclonedx-component, cyclonedx-service, cyclonedx-dependency, cyclonedx-composition, cyclonedx-vulnerability, cyclonedx-annotation, cyclonedx-formulation, cyclonedx-declaration, cyclonedx-definition, cyclonedx-citation, cyclonedx-perspective, cyclonedx-common, cyclonedx-party, cyclonedx-license, cyclonedx-data, cyclonedx-cryptography, cyclonedx-ai-modelcard, cyclonedx-release-notes, cyclonedx-standard, cyclonedx-patent, cyclonedx-jss_X590_2023_10, cyclonedx-api) and check whether the schema makes sense in its current structure. Specifically verify:
Code

- Broken references: every `$ref` (relative file path + JSON pointer like `#/$defs/xyz`) resolves to an existing file and an existing $defs entry in that file. List any $ref that points to a missing file or missing definition.
- `$id` consistency: each file's $id matches its actual path/filename and the expected https://cyclonedx.org/schema/2.0/... convention.
Orphaned files/definitions: model files or $defs entries not reachable from the root schema (excluding the separate cyclonedx-api-2.0.schema.json entry point — check its refs too).
- Circular references that could be problematic, and duplicate definitions of the same concept in multiple files.
- Draft 2020-12 correctness: proper use of $defs, unevaluatedProperties interaction with allOf/$ref (note the root uses unevaluatedProperties: false together with allOf extensibleProperties — check whether this composition works as intended across files), missing $schema declarations, wrong keyword usage, invalid regex patterns, enum/const misuse.
- Naming/structural inconsistencies: inconsistent def naming, inconsistent title/description conventions, anything that looks off (e.g. typos in filenames like jss_X590 vs X.509).

Produce a report of concrete issues found, each with file path, JSON pointer location, and a suggested fix. Also state explicitly which aspects were checked and found to be fine.

I need the report in pastable markdown.

report:

CycloneDX 2.0 JSON Schema Structure Review

Scope: branch 2.0-tests-init-fixes, schema/2.0/cyclonedx-2.0.schema.json + schema/2.0/cyclonedx-api-2.0.schema.json + all 34 files in schema/2.0/model/, excluding *-bundled* files. All $refs followed transitively; every file metaschema-validated against JSON Schema draft 2020-12.


1. Broken / fragile references

All intra-schema/2.0 refs resolve correctly (file + #/$defs/... pointer) — 0 hard-broken refs among the 36 files. However, five refs escape the versioned tree via ../../ and two of them have a real identifier mismatch:

# File / JSON pointer Ref Issue Suggested fix
1.1 model/cyclonedx-cryptography-2.0.schema.json #/$defs/cryptoProperties/properties/algorithmProperties/properties/algorithmFamily ../../cryptography-defs.schema.json#/definitions/algorithmFamiliesEnum Target file exists and pointer exists, but the ref resolves (per RFC 3986 against the base $id) to https://cyclonedx.org/schema/cryptography-defs.schema.json, while that file declares "$id": "http://cyclonedx.org/schema/cryptography-defs.schema.json" (http vs https). $id-based resolvers/registries will fail to match. Also a draft-07 file (definitions, not $defs) referenced from a 2020-12 schema, and an unversioned dependency outside schema/2.0/. Update the external file's $id to https:// (or ref the http:// URI explicitly); long-term, snapshot a 2020-12 copy under schema/2.0/.
1.2 same file, .../properties/ellipticCurve ../../cryptography-defs.schema.json#/definitions/ellipticCurvesEnum Same as 1.1. Same as 1.1.
1.3 model/cyclonedx-license-2.0.schema.json #/$defs/license/properties/id ../../spdx.schema.json Target exists, but resolves to https://cyclonedx.org/schema/spdx.schema.json while the file declares "$id": "http://cyclonedx.org/schema/spdx.schema.json" — same http/https mismatch; draft-07 target. Same as 1.1.
1.4 model/cyclonedx-behavior-2.0.schema.json #/$defs/behaviorInstance/properties/behavior and #/$defs/behaviorNode/properties/behavior ../../behavior-taxonomy.schema.json Resolves cleanly ($id is https://…, draft 2020-12) ✅ — but it is an unversioned dependency outside schema/2.0/; future edits to the shared file silently change 2.0 semantics. Consider versioning it under schema/2.0/ or pinning.

2. $id consistency — ✅ (within 2.0)

Every one of the 36 files has $id exactly matching https://cyclonedx.org/schema/2.0/<path> and its actual path/filename, and $schema: https://json-schema.org/draft/2020-12/schema. The only $id problems are the external http/https mismatches in 1.1–1.3.

3. Orphaned files / definitions

  • Files: none orphaned — all 34 model files are transitively reachable from the root schema. ✅
  • cyclonedx-api-2.0.schema.json is an empty stub: {"type": "object", "$defs": {}} — no properties, no refs. The README describes it as "the normative API-focused schema [that] reuses CycloneDX models", which it currently does not.
    Fix: implement it or mark it as a placeholder in the README.
  • Orphaned $defs (referenced from nowhere, including their own file):
Location Issue Suggested fix
model/cyclonedx-common-2.0.schema.json#/$defs/organizationalEntityOrContact Literally {"$comment": "TODO"} — an unfinished stub. Implement or delete.
model/cyclonedx-common-2.0.schema.json#/$defs/timestamp Unused, while 48 places across the corpus inline "format": "date-time" without a pattern. In 2020-12, format is annotation-only by default, so those 48 timestamps are effectively unvalidated, and the one def that does validate (format + pattern) is dead. Ref common#/$defs/timestamp everywhere (or delete it and accept format-only).
model/cyclonedx-common-2.0.schema.json#/$defs/base64 Unused; common#/$defs/attachment declares encoding: enum ["base64"] but never validates content against this pattern. Wire it into attachment (e.g. via if/then on encoding) or delete.
model/cyclonedx-common-2.0.schema.json#/$defs/baseObject The "mixin base object for all CycloneDX entities" (composes extensibleProperties) is dead code — nothing refs it. Consequence: only the document root composes extensibleProperties; every other object is closed with additionalProperties: false, so the ext:<namespace>:<name> extension mechanism is unusable anywhere except the BOM top level. Either have entity defs compose baseObject/extensibleProperties + unevaluatedProperties: false, or delete baseObject and document that extensions are root-only.

4. Circular references & duplicate definitions

  • File-level cycle: cyclonedx-component-2.0.schema.jsoncyclonedx-ai-modelcard-2.0.schema.json (component → modelCard, graphicsCollection; ai-modelcard → componentData). Fully resolvable for validators — not problematic, but worth knowing for code generators. Self-recursive defs (nested components, dependency graph, etc.) are standard and fine.
  • Duplicate $defs names across files (14): dependency, flow, hashAlgorithm, identifier (×3), metadata, postalAddress, rating, requirement, requirements, risk, signatures, step, timestamp, trigger.
    • True concept duplicate: postalAddress in common vs party — the party version is a superset (adds isoCode, coordinates). Two competing address models. Fix: keep one (party's) and ref it; delete/alias the other.
    • Intentional but collision-prone: hashAlgorithm and timestamp in cyclonedx-jss_X590_2023_10 deliberately differ from common (IANA names / X.590 clause 6.1 millisecond rule). Fine semantically, but same-named defs across files will clash in naive bundlers/codegen. Fix: prefix jss defs (e.g. jssTimestamp) or namespace during bundling.
    • The rest (dependency in dependency vs requirement, flow, metadata, identifier, rating, risk, step, trigger, …) are genuinely different domain concepts sharing generic names — acceptable, same bundling caveat.

5. Draft 2020-12 correctness

  • Metaschema validation: 0 violations in all 36 files.
  • Regex patterns: all pattern/patternProperties compile.
  • Root composition (unevaluatedProperties: false + allOf: [$ref → common#/$defs/extensibleProperties]): works as intended. In 2020-12, unevaluatedProperties sees annotations from patternProperties inside schemas reached through allOf/$ref, so ext:… properties are correctly allowed at the root while unknown properties are rejected. ✅
  • additionalProperties: false + allOf combinations (e.g. component#/$defs/component, behavior#/$defs/behaviorGraph|behaviorNode, vulnerability#/$defs/presenceEvidence, threat categories): verified that no allOf branch introduces property names absent from the parent's properties — all branches are not/if-then constraints on declared properties, so nothing is falsely rejected. ✅ However, this closes those objects to ext: extensions (see §3 baseObject) and mixes two closure idioms (additionalProperties: false vs the root's unevaluatedProperties: false). Suggested fix: standardise on one idiom per the intended extensibility model.
  • $schema declarations: present and correct in every file. ✅ No legacy keywords (definitions, boolean exclusiveMinimum, additionalItems) anywhere. ✅ (cyclonedx-definition-2.0.schema.json#/$defs/definitions is a def named "definitions", not the keyword — legal, mildly confusing.)
  • specVersion is unconstrained: cyclonedx-2.0.schema.json#/properties/specVersion is required but has only examples: ["2.0"] — any string validates. 1.x schemas pinned it with enum. Fix: add "const": "2.0" (or an enum/pattern).
  • Single-value enums (prefer const): cyclonedx-2.0.schema.json#/properties/specFormat (["CycloneDX"]), ai-modelcard#/$defs/energyMeasure/properties/unit (["kWh"]), ai-modelcard#/$defs/co2Measure/properties/unit (["tCO2eq"]), common#/$defs/attachment/properties/encoding (["base64"]), evidence#/$defs/assessmentMethod/allOf/1/.../not (["filename"]). Cosmetic.
  • jss…#/$defs/signatureObject sets unevaluatedProperties: true: redundant (open is the default) but intentional and documented via $comment citing X.590 clause 6.2. OK as-is.
  • Non-standard meta:enum keyword: used consistently and every meta:enum key set exactly matches its sibling enum values ✅ (established CycloneDX 1.6/1.7 convention).

6. Naming / structural inconsistencies

Location Issue Suggested fix
model/cyclonedx-jss_X590_2023_10-2.0.schema.json Not a typo: ITU‑T X.590 (2023‑10) is the JSON Signature Scheme (JSS) — distinct from X.509; common#/$defs/signatures even links the ITU X.590 publication. Only the style is inconsistent: underscores + embedded date vs the hyphenated, undated names of every other file. Optionally rename to e.g. cyclonedx-jss-x590-2.0.schema.json for consistency.
jss signatureObject properties snake_case (hash_algorithm, public_key, cert_url, valid_from, …) vs camelCase everywhere else — intentional (X.590 wire format), but worth a $comment if not already obvious. Document; keep as-is.
Root container shape inconsistency components, dependencies, compositions, vulnerabilities, controls, annotations, formulation, blueprints, citations, perspectives are arrays, but threats, risks, declarations, definitions, profiles are objects wrapping same-named arrays (bom.threats.threats[], bom.risks.risks[]). Accept (matches 1.6 declarations precedent) or flatten for uniformity; at minimum document the convention.
26 of 307 $defs lack title e.g. common#/$defs/refType, refLinkType, component#/$defs/version, versionRange, componentData, composition#/$defs/aggregateType, formulation#/$defs/step, command, … Add titles for doc-generation consistency.
schema/2.0/README.md Table references cyclonedx-api-2.0-bundled.schema.json, which does not exist. Create it or remove the row.
schema/2.0/model/README.md Badly stale: lists 4 nonexistent files (cyclonedx-ai-model-parameters, cyclonedx-licensing, cyclonedx-patent-assertion, cyclonedx-patent-family) and omits ~16 real files (behavior, blueprint, business-objective, certification, citation, control, data, evidence, jss, party, perspective, physical, profile, requirement, risk, threat, usecase, weakness). Regenerate the model index.
component#/$defs/component/properties/mime-type Kebab-case like legacy bom-ref; everything else camelCase. Accept as 1.x-compat or rename (mimeType) since 2.0 is a breaking release.

7. Explicitly checked and found fine

  • ✅ All 36 files parse as valid JSON and validate against the draft 2020-12 metaschema (0 errors).
  • ✅ All intra-schema/2.0 $refs (file + #/$defs/... pointer) resolve; all pointers into external files (#/definitions/...) also exist.
  • $id ↔ path/filename convention correct in all 36 files; $schema present everywhere.
  • ✅ No orphaned model files — every model file is reachable from the root schema.
  • ✅ Root unevaluatedProperties: false + allOf → extensibleProperties composition behaves correctly under 2020-12 annotation rules.
  • ✅ No additionalProperties: false object is broken by its allOf branches (no branch declares undeclared property names).
  • ✅ All regexes compile; serialNumber urn:uuid pattern is correct; patternProperties ^ext:...$ anchored correctly.
  • ✅ No required entries missing from properties in closed objects; no duplicate required entries; no unknown format values; no $ref siblings that add conflicting constraints; meta:enum fully consistent with enum everywhere; $defs names uniformly lowerCamelCase.
  • jss_X590 filename is not an X.509 typo — it correctly references ITU-T X.590 (JSS), edition 2023-10.

Priority fixes (summary)

  1. Fix http vs https $id mismatch in schema/cryptography-defs.schema.json and schema/spdx.schema.json (breaks $id-based ref resolution from 2.0).
  2. Resolve the dead extensibility design: orphaned baseObject + closed objects means ext: properties only work at the BOM root.
  3. Implement or clearly stub cyclonedx-api-2.0.schema.json; add the missing cyclonedx-api-2.0-bundled.schema.json or fix the README.
  4. Finish or remove common#/$defs/organizationalEntityOrContact (TODO stub); wire up or remove orphaned timestamp/base64 defs (and add pattern to the 48 unvalidated date-time fields if strict validation is intended).
  5. Constrain specVersion (e.g. const: "2.0").
  6. Deduplicate postalAddress (common vs party); regenerate model/README.md.

actions taken:

  1. will not do. the schema has an existing and working and in-use ID
  2. might consider - not in the scope of this PR
  3. out of scope for this PR
  4. out of scope of this PR
  5. not planned. it is a free string that needs to stay like this for compatibility reasons with future/previous releases.

@jkowalleck
jkowalleck marked this pull request as ready for review August 21, 2026 16:00
@taleodor

This comment was marked as off-topic.

@jkowalleck

This comment was marked as off-topic.

@jkowalleck

This comment was marked as outdated.

Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
@jkowalleck jkowalleck added test-data related to test-resources and -data format: JSON and removed chore A chore labels Aug 24, 2026
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
@jkowalleck
jkowalleck merged commit caf17eb into 2.0-dev Aug 24, 2026
13 checks passed
@jkowalleck
jkowalleck deleted the 2.0-tests-init-fixes branch August 24, 2026 14:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CDX 2.0 related to release v2.0 defect format: JSON ready for review test-data related to test-resources and -data

Projects

None yet

3 participants