mirror of
https://github.com/anchore/syft.git
synced 2026-11-04 00:16:38 +01:00
Canonicalize Ghostscript CPE/PURL for ghostscript packages from PE Binaries (#4308)
* binary(pe): canonicalize Ghostscript CPE to artifex:ghostscript and add generic purl for PE (#4275)\n\n- Detect Ghostscript via PE version resources and set purl pkg:generic/ghostscript@<version>\n- Add PE-specific CPE candidates: vendor 'artifex', product 'ghostscript'\n- Add focused unit tests for purl and CPE generation Signed-off-by: kdt523 <krushna.datir231@vit.edu> * fix: gofmt formatting for static analysis pass (pe-ghostscript-cpe-purl-4275) Signed-off-by: kdt523 <krushna.datir231@vit.edu> --------- Signed-off-by: kdt523 <krushna.datir231@vit.edu>
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
package cpegenerate
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
)
|
||||
|
||||
// candidateVendorsForPE returns vendor candidates for PE (BinaryPkg) packages based on common metadata hints.
|
||||
// Specifically, normalize Ghostscript binaries to vendor "artifex" when detected.
|
||||
func candidateVendorsForPE(p pkg.Package) fieldCandidateSet {
|
||||
candidates := newFieldCandidateSet()
|
||||
|
||||
meta, ok := p.Metadata.(pkg.PEBinary)
|
||||
if !ok {
|
||||
return candidates
|
||||
}
|
||||
|
||||
var company, product, fileDesc string
|
||||
for _, kv := range meta.VersionResources {
|
||||
switch strings.ToLower(kv.Key) {
|
||||
case "companyname":
|
||||
company = strings.ToLower(kv.Value)
|
||||
case "productname":
|
||||
product = strings.ToLower(kv.Value)
|
||||
case "filedescription":
|
||||
fileDesc = strings.ToLower(kv.Value)
|
||||
}
|
||||
}
|
||||
|
||||
if strings.Contains(product, "ghostscript") || strings.Contains(fileDesc, "ghostscript") || strings.Contains(company, "artifex") {
|
||||
candidates.addValue("artifex")
|
||||
}
|
||||
|
||||
return candidates
|
||||
}
|
||||
|
||||
// candidateProductsForPE returns product candidates for PE (BinaryPkg) packages based on common metadata hints.
|
||||
// Specifically, normalize Ghostscript binaries to product "ghostscript" when detected.
|
||||
func candidateProductsForPE(p pkg.Package) fieldCandidateSet {
|
||||
candidates := newFieldCandidateSet()
|
||||
|
||||
meta, ok := p.Metadata.(pkg.PEBinary)
|
||||
if !ok {
|
||||
return candidates
|
||||
}
|
||||
|
||||
var product, fileDesc string
|
||||
for _, kv := range meta.VersionResources {
|
||||
switch strings.ToLower(kv.Key) {
|
||||
case "productname":
|
||||
product = strings.ToLower(kv.Value)
|
||||
case "filedescription":
|
||||
fileDesc = strings.ToLower(kv.Value)
|
||||
}
|
||||
}
|
||||
|
||||
if strings.Contains(product, "ghostscript") || strings.Contains(fileDesc, "ghostscript") {
|
||||
candidates.addValue("ghostscript")
|
||||
}
|
||||
|
||||
return candidates
|
||||
}
|
||||
@@ -225,6 +225,9 @@ func candidateVendors(p pkg.Package) []string {
|
||||
vendors.union(candidateVendorsForAPK(p))
|
||||
case pkg.NpmPackage:
|
||||
vendors.union(candidateVendorsForJavascript(p))
|
||||
case pkg.PEBinary:
|
||||
// Add PE-specific vendor hints (e.g. ghostscript -> artifex)
|
||||
vendors.union(candidateVendorsForPE(p))
|
||||
case pkg.WordpressPluginEntry:
|
||||
vendors.clear()
|
||||
vendors.union(candidateVendorsForWordpressPlugin(p))
|
||||
@@ -301,6 +304,9 @@ func candidateProductSet(p pkg.Package) fieldCandidateSet {
|
||||
switch p.Metadata.(type) {
|
||||
case pkg.ApkDBEntry:
|
||||
products.union(candidateProductsForAPK(p))
|
||||
case pkg.PEBinary:
|
||||
// Add PE-specific product hints (e.g. ghostscript)
|
||||
products.union(candidateProductsForPE(p))
|
||||
case pkg.WordpressPluginEntry:
|
||||
products.clear()
|
||||
products.union(candidateProductsForWordpressPlugin(p))
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package cpegenerate
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
)
|
||||
|
||||
func TestGhostscriptPEGeneratesArtifexCPE(t *testing.T) {
|
||||
// construct a BinaryPkg with PE metadata resembling Ghostscript
|
||||
p := pkg.Package{
|
||||
Name: "GPL Ghostscript",
|
||||
Version: "9.54.0",
|
||||
Type: pkg.BinaryPkg,
|
||||
Metadata: pkg.PEBinary{
|
||||
VersionResources: pkg.KeyValues{
|
||||
{Key: "CompanyName", Value: "Artifex Software, Inc."},
|
||||
{Key: "ProductName", Value: "GPL Ghostscript"},
|
||||
{Key: "FileDescription", Value: "Ghostscript Interpreter"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
cpes := FromPackageAttributes(p)
|
||||
if len(cpes) == 0 {
|
||||
t.Fatalf("expected at least one CPE, got none")
|
||||
}
|
||||
|
||||
found := false
|
||||
for _, c := range cpes {
|
||||
if c.Attributes.Vendor == "artifex" && c.Attributes.Product == "ghostscript" && c.Attributes.Version == p.Version {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatalf("expected to find CPE with vendor 'artifex' and product 'ghostscript' for Ghostscript PE binary; got: %+v", cpes)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user