From fb85c70353bae6b4af8aa3f312297ba045c2680a Mon Sep 17 00:00:00 2001 From: Mikail Kocak Date: Thu, 29 Aug 2024 16:24:08 +0200 Subject: [PATCH] fix: properly decode SPDX license expressions in CycloneDX format This fixes the issue reported at https://github.com/anchore/syft/issues/3172, where Syft would drop SPDX licenses due a logic error in the decoder. CycloneDX specifications require `components[].licenses[].license` to be nil when `components[].licenses[].expression` (SPDX) is non nil. Signed-off-by: Mikail Kocak --- syft/format/internal/cyclonedxutil/helpers/licenses.go | 9 +++------ .../internal/cyclonedxutil/helpers/licenses_test.go | 4 ++-- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/syft/format/internal/cyclonedxutil/helpers/licenses.go b/syft/format/internal/cyclonedxutil/helpers/licenses.go index a092d3abdf3b..24c5d6ffb79c 100644 --- a/syft/format/internal/cyclonedxutil/helpers/licenses.go +++ b/syft/format/internal/cyclonedxutil/helpers/licenses.go @@ -54,17 +54,14 @@ func decodeLicenses(c *cyclonedx.Component) []pkg.License { } for _, l := range *c.Licenses { - if l.License == nil { - continue - } // these fields are mutually exclusive in the spec switch { - case l.License.ID != "": + case l.License != nil && l.License.ID != "": licenses = append(licenses, pkg.NewLicenseFromURLs(l.License.ID, l.License.URL)) - case l.License.Name != "": + case l.License != nil && l.License.Name != "": licenses = append(licenses, pkg.NewLicenseFromURLs(l.License.Name, l.License.URL)) case l.Expression != "": - licenses = append(licenses, pkg.NewLicenseFromURLs(l.Expression, l.License.URL)) + licenses = append(licenses, pkg.NewLicense(l.Expression)) default: } } diff --git a/syft/format/internal/cyclonedxutil/helpers/licenses_test.go b/syft/format/internal/cyclonedxutil/helpers/licenses_test.go index e2532f607d45..373a09377589 100644 --- a/syft/format/internal/cyclonedxutil/helpers/licenses_test.go +++ b/syft/format/internal/cyclonedxutil/helpers/licenses_test.go @@ -254,7 +254,8 @@ func TestDecodeLicenses(t *testing.T) { input: &cyclonedx.Component{ Licenses: &cyclonedx.Licenses{ { - License: &cyclonedx.License{}, + // CycloneDX specification doesn't allow to provide License if Expression is provided + License: nil, Expression: "MIT AND GPL-3.0-only WITH Classpath-exception-2.0", }, }, @@ -264,7 +265,6 @@ func TestDecodeLicenses(t *testing.T) { Value: "MIT AND GPL-3.0-only WITH Classpath-exception-2.0", SPDXExpression: "MIT AND GPL-3.0-only WITH Classpath-exception-2.0", Type: license.Declared, - URLs: []string{}, }, }, },