fix(cyclonedx): conditionally exclude group from package name (#4791)

Signed-off-by: David Dashti <david.dashti@hermesmedical.com>
This commit is contained in:
David Dashti 2026-04-18 02:21:21 +02:00 committed by GitHub
parent 26175d74f8
commit 076fb211cc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 65 additions and 3 deletions

View File

@ -151,13 +151,13 @@ var epochPrefix = regexp.MustCompile(`^\d+:`)
// nameFromPurl returns the syft package name of the package from the purl. If the purl includes a namespace, // nameFromPurl returns the syft package name of the package from the purl. If the purl includes a namespace,
// the name is prefixed as appropriate based on the PURL type // the name is prefixed as appropriate based on the PURL type
func nameFromPurl(purl packageurl.PackageURL) string { func nameFromPurl(purl packageurl.PackageURL) string {
if !nameExcludesPurlNamespace(purl.Type) && purl.Namespace != "" { if !NameExcludesPurlNamespace(purl.Type) && purl.Namespace != "" {
return fmt.Sprintf("%s/%s", purl.Namespace, purl.Name) return fmt.Sprintf("%s/%s", purl.Namespace, purl.Name)
} }
return purl.Name return purl.Name
} }
func nameExcludesPurlNamespace(purlType string) bool { func NameExcludesPurlNamespace(purlType string) bool {
switch purlType { switch purlType {
case packageurl.TypeAlpine, case packageurl.TypeAlpine,
packageurl.TypeAlpm, packageurl.TypeAlpm,

View File

@ -165,6 +165,7 @@ func getPURL(c *cyclonedx.Component, ty pkg.Type) string {
return purl.ToString() return purl.ToString()
} }
//nolint:gocognit
func setPackageName(p *pkg.Package, c *cyclonedx.Component) { func setPackageName(p *pkg.Package, c *cyclonedx.Component) {
name := c.Name name := c.Name
if c.Group != "" { if c.Group != "" {
@ -195,9 +196,11 @@ func setPackageName(p *pkg.Package, c *cyclonedx.Component) {
} }
} }
default: default:
if !internal.NameExcludesPurlNamespace(p.Type.PackageURLType()) {
name = fmt.Sprintf("%s/%s", c.Group, name) name = fmt.Sprintf("%s/%s", c.Group, name)
} }
} }
}
p.Name = name p.Name = name
} }

View File

@ -384,6 +384,65 @@ func Test_decodeComponent(t *testing.T) {
} }
} }
func Test_setPackageName(t *testing.T) {
tests := []struct {
name string
pkg pkg.Package
comp cyclonedx.Component
wantName string
}{
{
name: "debian group excluded from name",
pkg: pkg.Package{Type: pkg.DebPkg},
comp: cyclonedx.Component{Name: "wget", Group: "debian"},
wantName: "wget",
},
{
name: "rpm group excluded from name",
pkg: pkg.Package{Type: pkg.RpmPkg},
comp: cyclonedx.Component{Name: "acl", Group: "centos"},
wantName: "acl",
},
{
name: "apk group excluded from name",
pkg: pkg.Package{Type: pkg.ApkPkg},
comp: cyclonedx.Component{Name: "musl", Group: "alpine"},
wantName: "musl",
},
{
name: "npm group included in name",
pkg: pkg.Package{Type: pkg.NpmPkg},
comp: cyclonedx.Component{Name: "node", Group: "@types"},
wantName: "@types/node",
},
{
name: "go module group included in name",
pkg: pkg.Package{Type: pkg.GoModulePkg},
comp: cyclonedx.Component{Name: "net", Group: "golang.org/x"},
wantName: "golang.org/x/net",
},
{
name: "no group leaves name unchanged",
pkg: pkg.Package{Type: pkg.DebPkg},
comp: cyclonedx.Component{Name: "wget"},
wantName: "wget",
},
{
name: "java group stored in metadata not name",
pkg: pkg.Package{Type: pkg.JavaPkg},
comp: cyclonedx.Component{Name: "log4j", Group: "org.apache.logging.log4j"},
wantName: "log4j",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
p := tt.pkg
setPackageName(&p, &tt.comp)
assert.Equal(t, tt.wantName, p.Name)
})
}
}
func TestGetPURL(t *testing.T) { func TestGetPURL(t *testing.T) {
tests := []struct { tests := []struct {
name string name string