CycloneDX / CycloneDX/cyclonedx-cli
Bug in merging json SBOMs with empty component lists
- Dominant language
- C#
- Stars
- 541
- Forks
- 82
- PR merge metrics
- No merged PRs in 30d
Description
When merging multiple SBOMs and specifying the `--name` and `--version` arguments, then the top level components of the SBOMs must be added to the components list of the new merged SBOM. However, if the input SBOMs are missing the `components` property, then the top level components of the input SBOMs will not be added to the list of components of the merged SBOM.
Reproduction:
Consider the following 3 minimal SBOMs
### bom1.json
```json
{
"bomFormat": "CycloneDX",
"specVersion": "1.5",
"serialNumber": "urn:uuid:957c05a9-5f45-4fhm-aaa1-49df4c08c61a",
"version": 1,
"metadata": {
"timestamp": "2024-04-18T11:24:03Z",
"component": {
"type": "container",
"bom-ref": "container1",
"name": "container1",
"version": "1",
"purl": "container1@1"
}
},
"dependencies": [
{
"dependsOn": [],
"ref": "container1@1"
}
]
}
```
### bom2.json
```json
{
"bomFormat": "CycloneDX",
"specVersion": "1.5",
"serialNumber": "urn:uuid:957c05a9-5f39-4fca-aaa1-49df4c08c61a",
"version": 1,
"metadata": {
"timestamp": "2024-04-18T11:24:03Z",
"component": {
"type": "container",
"bom-ref": "container2",
"name": "container2",
"version": "2",
"purl": "container2@2"
}
},
"dependencies": [
{
"dependsOn": [],
"ref": "container2@2"
}
]
}
```
### bom3.json
```json
{
"bomFormat": "CycloneDX",
"specVersion": "1.5",
"serialNumber": "urn:uuid:957c05a9-5f39-4fca-69a1-69df4c08c61a",
"version": 1,
"metadata": {
"timestamp": "2024-04-18T11:24:03Z",
"component": {
"type": "container",
"bom-ref": "container3",
"name": "container3",
"version": "3",
"purl": "container3@3"
}
},
"dependencies": [
{
"dependsOn": [],
"ref": "container3@3"
}
]
}
```
### merged.json
Now let's merge the 3 input SBOMs:
`cyclonedx-win-x64.exe merge --input-files "bom1.json" "bom2.json" "bom3.json" --output-file "merged.json" --name "merged" --version "merged"`
Result:
```json
{
"bomFormat": "CycloneDX",
"specVersion": "1.5",
"serialNumber": "urn:uuid:adb22d1b-748e-4731-93ce-9d360816a3c9",
"version": 1,
"metadata": {
"component": {
"type": "application",
"name": "merged",
"version": "merged"
}
},
"dependencies": [
{
"ref": "container1@1",
"dependsOn": []
},
{
"ref": "container2@2",
"dependsOn": []
},
{
"ref": "container3@3",
"dependsOn": []
}
]
}
```
As you can see in the result, the `components` property is missing and the top level components of the input SBOMs are lost. Interestingly, components would be added only after first input SBOM that contains a `components` property is merged. If `bom2.json` contains the `components` property, then the result would be:
### bom2.json
```json
{
"bomFormat": "CycloneDX",
"specVersion": "1.5",
"serialNumber": "urn:uuid:957c05a9-5f39-4fca-aaa1-49df4c08c61a",
"version": 1,
"metadata": {
"timestamp": "2024-04-18T11:24:03Z",
"component": {
"type": "container",
"bom-ref": "container2",
"name": "container2",
"version": "2",
"purl": "container2@2"
}
},
"dependencies": [
{
"dependsOn": [],
"ref": "container2@2"
}
],
"components": [] # The components property is now present
}
```
### merged.json
```json
{
"bomFormat": "CycloneDX",
"specVersion": "1.5",
"serialNumber": "urn:uuid:fa30d92e-4d22-4c38-9337-7f2ec7ea0e0a",
"version": 1,
"metadata": {
"component": {
"type": "application",
"name": "merged",
"version": "merged"
}
},
"components": [
{
"type": "container",
"bom-ref": "container2",
"name": "container2",
"version": "2",
"purl": "container2@2"
},
{
"type": "container",
"bom-ref": "container3",
"name": "container3",
"version": "3",
"purl": "container3@3"
}
],
"dependencies": [
{
"ref": "container1@1",
"dependsOn": []
},
{
"ref": "container2@2",
"dependsOn": []
},
{
"ref": "container3@3",
"dependsOn": []
}
]
}
```
Contributor guide
Assessment
This issue has not been assessed yet.