Skip to content

Merging objects with non-unique bom_refs silently introduces data inconsistency #807

@wkoot

Description

@wkoot

NB: this is an extension of #540 and #677

Given the testdata in #677, set up a test for #540 but with clashing bom_refs and unique names instead:

>>> from json import load
>>> from cyclonedx.model.bom import Bom
>>> from cyclonedx.model.component import Component, ComponentType
>>> root_component = Component(
...     type=ComponentType.FRAMEWORK,
...     name="root 42",
...     version="42",
...     bom_ref="root",
... )
>>>
>>> bom = Bom()
>>> bom.metadata.component = root_component
>>> bom.validate()
True
>>> len(bom.components)
0
>>> len(bom.dependencies)
1
>>>
>>> with open('out.json', mode="r") as testfile:
...  json_bom = load(testfile)
...
>>> len(json_bom['components'])
4
>>> len(json_bom['dependencies'])
3
>>>
>>> loaded_bom = Bom.from_json(json_bom)
>>> loaded_bom.validate()
True
>>> len(loaded_bom.components)
4
>>> len(loaded_bom.dependencies)
5
>>>
>>> loaded_bom.metadata.component
<Component bom-ref=<BomRef 'root' id=139844009673936>, group=None, name=test, version=None, type=ComponentType.APPLICATION>
>>> bom.metadata.component
<Component bom-ref=<BomRef 'root' id=139844025859088>, group=None, name=root 42, version=42, type=ComponentType.FRAMEWORK>
>>>
>>> loaded_bom.metadata.component.bom_ref
<BomRef 'root' id=139844009673936>
>>> bom.metadata.component.bom_ref
<BomRef 'root' id=139844025859088>
>>>
>>> bom.metadata.component.bom_ref == loaded_bom.metadata.component.bom_ref
True
>>> loaded_bom.metadata.component == bom.metadata.component
False
>>>
>>> bom.components.add(loaded_bom.metadata.component)
>>> bom.register_dependency(root_component, [loaded_bom.metadata.component])
>>> bom.components |= loaded_bom.components
>>> bom.dependencies |= loaded_bom.dependencies
>>>
>>> bom.validate()
True
>>>
>>> len(bom.components)
5
>>> len(bom.dependencies)
6

Note that the Bom says it is valid, while it is actually not - although this is not apparent at a glance.
When outputting to json (e.g. with the reported JsonV1Dot5), dependencies is shown to be as follows:

        [
            {"ref": "root", "dependsOn": ["BomRef.23942051401152453.4412489734431171"]},
            {"ref": "root", "dependsOn": ["test11", "test21"]},
            {"ref": "test11", "dependsOn": ["test12"]},
            {"ref": "test12"},
            {"ref": "test21", "dependsOn": ["test22"]},
            {"ref": "test22"}
        ]

This is actually invalid and would not validate when dumped to file and re-read by the library

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions