cyclonedx: import firmware-typed components as packages (#4855)

The CycloneDX decoder was filtering on a hard-coded set of component
types (application/framework/library/machine-learning-model). Anything
else — including "firmware" — fell through silently, so a BOM
describing u-boot or other firmware ended up with no packages and
grype reported no matches (anchore/grype#2537).

@kzantow confirmed in the issue thread that firmware should be
included and gave this section as the spot to update.

Add ComponentTypeFirmware to the case list and a regression test that
constructs a single-firmware-component BOM and asserts the decoded
SBOM contains the package.

Closes anchore/grype#2537

Signed-off-by: Chris (ChrisJr404) <11917633+ChrisJr404@users.noreply.github.com>
Co-authored-by: Chris (ChrisJr404) <11917633+ChrisJr404@users.noreply.github.com>
This commit is contained in:
ChrisJr404 2026-07-13 15:33:51 -04:00 committed by GitHub
parent fabd760914
commit 4312699dd6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 25 additions and 1 deletions

View File

@ -62,7 +62,7 @@ func collectPackages(component *cyclonedx.Component, s *sbom.SBOM, idMap map[str
switch component.Type {
case cyclonedx.ComponentTypeOS:
case cyclonedx.ComponentTypeContainer:
case cyclonedx.ComponentTypeApplication, cyclonedx.ComponentTypeFramework, cyclonedx.ComponentTypeLibrary, cyclonedx.ComponentTypeMachineLearningModel:
case cyclonedx.ComponentTypeApplication, cyclonedx.ComponentTypeFramework, cyclonedx.ComponentTypeLibrary, cyclonedx.ComponentTypeMachineLearningModel, cyclonedx.ComponentTypeFirmware:
p := decodeComponent(component)
idMap[component.BOMRef] = p
if component.BOMRef != "" {

View File

@ -259,6 +259,30 @@ func Test_decode(t *testing.T) {
}
}
func Test_decode_includesFirmwareComponents(t *testing.T) {
// CycloneDX BOMs that describe firmware (e.g. u-boot) use
// component type "firmware". Prior to issue #2537 the decoder skipped
// these and downstream tools (e.g. grype) reported zero matches.
bom := cyclonedx.BOM{
Components: &[]cyclonedx.Component{
{
BOMRef: "u-boot",
Type: cyclonedx.ComponentTypeFirmware,
Name: "u-boot",
Version: "2024.04",
PackageURL: "pkg:generic/u-boot@2024.04",
},
},
}
model, err := ToSyftModel(&bom)
require.NoError(t, err)
pkgs := model.Artifacts.Packages.Sorted()
require.Len(t, pkgs, 1, "firmware component should be imported as a package")
assert.Equal(t, "u-boot", pkgs[0].Name)
assert.Equal(t, "2024.04", pkgs[0].Version)
}
func Test_relationshipDirection(t *testing.T) {
cyclonedx_bom := cyclonedx.BOM{Metadata: nil,
Components: &[]cyclonedx.Component{