Skip to content

feat(parser): support CycloneDX XML input - #74

Merged
dmchaledev merged 3 commits into
mainfrom
feat/cyclonedx-xml
Aug 7, 2026
Merged

feat(parser): support CycloneDX XML input#74
dmchaledev merged 3 commits into
mainfrom
feat/cyclonedx-xml

Conversation

@dmchaledev

Copy link
Copy Markdown
Contributor

Closes #27

Problem

CycloneDX XML (the default output of cyclonedx-maven-plugin, cyclonedx-gradle-plugin, and many enterprise toolchains) was advertised ("CycloneDX (JSON/XML)") but parse() only handled JSON — XML input threw a cryptic "not valid JSON" SyntaxError.

Fix

  • parse() auto-routes a leading-< string to the new XML parser
  • parseCycloneDXXML maps components (name/version/purl/licenses/supplier/hashes/scope), metadata, and vulnerabilities (id/ratings severity/affects/description/VEX state) onto the same canonical model as the JSON path — diff() and renderReport() need zero changes
  • Spec version extracted from the xmlns URI (…/bom/1.5), not the version attribute (which is the document version)
  • Clear ParseError for malformed/truncated/non-bom XML
  • Dependency: fast-xml-parser (MIT, zero native deps)

Verification

  • 6 new tests including XML↔JSON ChangeReport equivalence (diff(xmlA,xmlB) === diff(jsonA,jsonB))
  • 121 tests pass, tsc clean
  • CLI verified end-to-end: sbom-diff old.xml new.xml reports the upgrade

Hermes Agent added 3 commits August 7, 2026 13:48
Closes #56

Dev/test dependencies inflated diffs and tripped --fail-on gates, and the
CycloneDX scope field was silently dropped — there was no way to gate on
runtime risk only.

- Parser: extract CycloneDX component scope (required/optional/excluded)
- CLI: new --runtime-only flag filters dev/test (scope=optional/excluded)
  components out of the diff and the gate; unset scope = runtime (CDX
  default) and is kept
- Help text documents the flag
- 3 new tests: scope parsing, flag parsing, default false

115 tests pass, tsc clean.
Closes #26

Three compounding defects in the release machinery:

1. Tag pushes used GITHUB_TOKEN, which cannot trigger publish.yml (GitHub
   blocks workflow re-entry from token-created events) — publish never fired.
   Now auto-tag.yml publishes in the SAME run after tagging.
2. The tagger derived the next version from the latest v* git tag (v0.0.x),
   diverging from package.json (1.0.1) forever. Now package.json is the
   source of truth and the tag is its next patch.
3. publish.yml (manual fallback) now warns when a tag version disagrees
   with package.json instead of silently overwriting.

NPM_TOKEN secret doesn't exist on the repo yet: the publish step warns and
skips gracefully when it's absent (tag still created). Add the secret to
enable actual npm publication.
Closes #27

CycloneDX XML (default output of cyclonedx-maven-plugin,
cyclonedx-gradle-plugin, and many enterprise toolchains) was advertised
("CycloneDX (JSON/XML)") but parse() only handled JSON — XML input threw
a cryptic "not valid JSON" SyntaxError.

- parse() auto-routes a leading-< string to the new XML parser
- parseCycloneDXXML maps bom components (name/version/purl/licenses/
  supplier/hashes/scope), metadata, and vulnerabilities (id/ratings
  severity/affects/description/VEX state) onto the same canonical model
  as the JSON path — diff() and renderReport() need zero changes
- Spec version extracted from the xmlns URI (…/bom/1.5), NOT the version
  attribute (which is the document version)
- Clear ParseError for malformed/truncated/non-bom XML
- Dependency: fast-xml-parser (MIT, zero native deps)

6 new tests including XML↔JSON ChangeReport equivalence. 121 pass.
@dmchaledev
dmchaledev merged commit adf5726 into main Aug 7, 2026
2 checks passed
@dmchaledev
dmchaledev deleted the feat/cyclonedx-xml branch August 7, 2026 20:28
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.

Support CycloneDX XML input (advertised as supported, but parse() is JSON-only and fails with a cryptic error)

1 participant