Skip to content

Conversation

@jjhz
Copy link

@jjhz jjhz commented Sep 12, 2025

Fix #638

@mr-zepol Could you review this?

  • Fixes XML Serialization: Corrects the XML generation for component authors to produce schema-compliant <authors><author>...</author></authors> structure, resolving the issue of nested <authors> tags.
  • Add backward compatibility to support legecy format: <authors><authors>...</authors></authors>

When using cyclonedx-core-java to write a CycloneDX SBOM as an XML, the resulting SBOM is invalid (nested <authors> ag).

<?xml version="1.0" encoding="UTF-8"?>
<bom serialNumber="urn:uuid:e1acbeda-240f-4ab6-bd4e-749ab4183fec" version="1" xmlns="http://cyclonedx.org/schema/bom/1.6">
    <components>
        <component type="application">
            <authors>
                <authors>
                    <name>Test Author 1</name>
                    <email>[email protected]</email>
                    <phone>123</phone>
                </authors>
                <authors>
                    <name>Test Author 2</name>
                    <email>[email protected]</email>
                    <phone>456</phone>
                </authors>
            </authors>
            <author>Outer Author with String value</author>
            <name>Test Component</name>
        </component>
    </components>
</bom>

we should expect the author list to be:

<?xml version="1.0" encoding="UTF-8"?>
<bom serialNumber="urn:uuid:e1acbeda-240f-4ab6-bd4e-749ab4183fec" version="1" xmlns="http://cyclonedx.org/schema/bom/1.6">
    <components>
        <component type="application">
            <authors>
                <author>
                    <name>Test Author 1</name>
                    <email>[email protected]</email>
                    <phone>123</phone>
                </author>
                <author>
                    <name>Test Author 2</name>
                    <email>[email protected]</email>
                    <phone>456</phone>
                </author>
            </authors>
            <author>Outer Author with String value</author>
            <name>Test Component</name>
        </component>
    </components>
</bom>

@jjhz jjhz requested a review from a team as a code owner September 12, 2025 07:09
…thors to produce schema-compliant <authors><author>...</author></authors> structure, resolving the issue of nested <authors> tags.

Add backward compatibility to support legecy format: <authors><authors>...</authors></authors>

Signed-off-by: jjhz <[email protected]>
jjhz and others added 3 commits September 12, 2025 17:58
Signed-off-by: jjhz <[email protected]>
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.30.1 to 3.30.2.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](github/codeql-action@f1f6e5f...d3678e2)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 3.30.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
Signed-off-by: jjhz <[email protected]>
@jjhz jjhz changed the title Fix: XML serialization of components with authors results in invalid CycloneDX SBOM fix: XML serialization of components with authors results in invalid CycloneDX SBOM Sep 18, 2025
@codacy-production
Copy link

Coverage summary from Codacy

See diff coverage on Codacy

Coverage variation Diff coverage
+0.12% 100.00%
Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (d6dd3a9) 6456 4844 75.03%
Head commit (69d99e4) 6487 (+31) 4875 (+31) 75.15% (+0.12%)

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#708) 31 31 100.00%

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

See your quality gate settings    Change summary preferences

@mr-zepol
Copy link
Contributor

mr-zepol commented Oct 26, 2025

Fix #638

@mr-zepol Could you review this?

  • Fixes XML Serialization: Corrects the XML generation for component authors to produce schema-compliant <authors><author>...</author></authors> structure, resolving the issue of nested <authors> tags.
  • Add backward compatibility to support legecy format: <authors><authors>...</authors></authors>

When using cyclonedx-core-java to write a CycloneDX SBOM as an XML, the resulting SBOM is invalid (nested <authors> ag).

<?xml version="1.0" encoding="UTF-8"?>
<bom serialNumber="urn:uuid:e1acbeda-240f-4ab6-bd4e-749ab4183fec" version="1" xmlns="http://cyclonedx.org/schema/bom/1.6">
    <components>
        <component type="application">
            <authors>
                <authors>
                    <name>Test Author 1</name>
                    <email>[email protected]</email>
                    <phone>123</phone>
                </authors>
                <authors>
                    <name>Test Author 2</name>
                    <email>[email protected]</email>
                    <phone>456</phone>
                </authors>
            </authors>
            <author>Outer Author with String value</author>
            <name>Test Component</name>
        </component>
    </components>
</bom>

we should expect the author list to be:

<?xml version="1.0" encoding="UTF-8"?>
<bom serialNumber="urn:uuid:e1acbeda-240f-4ab6-bd4e-749ab4183fec" version="1" xmlns="http://cyclonedx.org/schema/bom/1.6">
    <components>
        <component type="application">
            <authors>
                <author>
                    <name>Test Author 1</name>
                    <email>[email protected]</email>
                    <phone>123</phone>
                </author>
                <author>
                    <name>Test Author 2</name>
                    <email>[email protected]</email>
                    <phone>456</phone>
                </author>
            </authors>
            <author>Outer Author with String value</author>
            <name>Test Component</name>
        </component>
    </components>
</bom>

Hey @jjhz

Thanks for working on this issue I've also been working on solving #638 independently and wanted to share my approach for comparison, I just have time to actually share what I did #730

I noticed a few potential considerations with the current PR:

  1. Version Filtering: With field-level @JsonSerialize annotations, there's a possibility the custom serializer might bypass the VersionXmlAnnotationIntrospector, which could result
    in the authors field appearing in v1.5 and earlier (where it's not supported). This would need testing to confirm.
  2. Deserializer: From my testing, Jackson handles deserialization naturally for both XML (...) and JSON ("authors": [...]) without needing custom logic. The deserializer might not be necessary.

I took a slightly different approach using a BeanSerializerModifier (similar to the existing CustomSerializerModifier pattern in the codebase), which:

  • Explicitly handles version filtering by removing the property for v1.5 and below, to avoid creating invalid SBOMs
  • Only requires a serializer (no deserializer needed)
  • Follows the existing architectural patterns in the project

I've created a comprehensive test suite (22 tests) covering all scenarios including version migrations, and everything passes including the full test suite.

My changes are on the issue_638 branch if you'd like to compare approaches. I'm happy to collaborate or discuss which solution would be best for the project!

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.

XML serialization of components with authors results in invalid CycloneDX SBOM

2 participants