mirror of
https://github.com/anchore/syft.git
synced 2025-11-18 17:03:17 +01:00
fix: add manual vendor/product removal to fix false flags (#1070)
Closes https://github.com/anchore/syft/issues/1066 Closes https://github.com/anchore/grype/issues/800 Closes https://github.com/anchore/grype/issues/491
This commit is contained in:
parent
f1a124209a
commit
668f102340
@ -11,6 +11,12 @@ type candidateComposite struct {
|
|||||||
candidateAddition
|
candidateAddition
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type candidateRemovalComposite struct {
|
||||||
|
pkg.Type
|
||||||
|
candidateKey
|
||||||
|
candidateRemovals
|
||||||
|
}
|
||||||
|
|
||||||
// defaultCandidateAdditions is all of the known cases for product and vendor field values that should be used when
|
// defaultCandidateAdditions is all of the known cases for product and vendor field values that should be used when
|
||||||
// select package information is discovered
|
// select package information is discovered
|
||||||
var defaultCandidateAdditions = buildCandidateLookup(
|
var defaultCandidateAdditions = buildCandidateLookup(
|
||||||
@ -123,6 +129,16 @@ var defaultCandidateAdditions = buildCandidateLookup(
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
var defaultCandidateRemovals = buildCandidateRemovalLookup(
|
||||||
|
[]candidateRemovalComposite{
|
||||||
|
// Python packages
|
||||||
|
{
|
||||||
|
pkg.PythonPkg,
|
||||||
|
candidateKey{PkgName: "redis"},
|
||||||
|
candidateRemovals{VendorsToRemove: []string{"redis"}},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
// buildCandidateLookup is a convenience function for creating the defaultCandidateAdditions set
|
// buildCandidateLookup is a convenience function for creating the defaultCandidateAdditions set
|
||||||
func buildCandidateLookup(cc []candidateComposite) (ca map[pkg.Type]map[candidateKey]candidateAddition) {
|
func buildCandidateLookup(cc []candidateComposite) (ca map[pkg.Type]map[candidateKey]candidateAddition) {
|
||||||
ca = make(map[pkg.Type]map[candidateKey]candidateAddition)
|
ca = make(map[pkg.Type]map[candidateKey]candidateAddition)
|
||||||
@ -136,12 +152,30 @@ func buildCandidateLookup(cc []candidateComposite) (ca map[pkg.Type]map[candidat
|
|||||||
return ca
|
return ca
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// buildCandidateRemovalLookup is a convenience function for creating the defaultCandidateRemovals set
|
||||||
|
func buildCandidateRemovalLookup(cc []candidateRemovalComposite) (ca map[pkg.Type]map[candidateKey]candidateRemovals) {
|
||||||
|
ca = make(map[pkg.Type]map[candidateKey]candidateRemovals)
|
||||||
|
for _, c := range cc {
|
||||||
|
if _, ok := ca[c.Type]; !ok {
|
||||||
|
ca[c.Type] = make(map[candidateKey]candidateRemovals)
|
||||||
|
}
|
||||||
|
ca[c.Type][c.candidateKey] = c.candidateRemovals
|
||||||
|
}
|
||||||
|
return ca
|
||||||
|
}
|
||||||
|
|
||||||
// candidateKey represents the set of inputs that should be matched on in order to signal more candidate additions to be used.
|
// candidateKey represents the set of inputs that should be matched on in order to signal more candidate additions to be used.
|
||||||
type candidateKey struct {
|
type candidateKey struct {
|
||||||
Vendor string
|
Vendor string
|
||||||
PkgName string
|
PkgName string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// candidateRemovals are the specific removals that should be considered during CPE generation (given a specific candidateKey)
|
||||||
|
type candidateRemovals struct {
|
||||||
|
ProductsToRemove []string
|
||||||
|
VendorsToRemove []string
|
||||||
|
}
|
||||||
|
|
||||||
// candidateAddition are the specific additions that should be considered during CPE generation (given a specific candidateKey)
|
// candidateAddition are the specific additions that should be considered during CPE generation (given a specific candidateKey)
|
||||||
type candidateAddition struct {
|
type candidateAddition struct {
|
||||||
AdditionalProducts []string
|
AdditionalProducts []string
|
||||||
@ -192,3 +226,35 @@ func findAdditionalProducts(allAdditions map[pkg.Type]map[candidateKey]candidate
|
|||||||
|
|
||||||
return products
|
return products
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// findVendorsToRemove searches all possible vendor removals that could be removed during the CPE generation process (given package info + a vendor candidate)
|
||||||
|
func findVendorsToRemove(allRemovals map[pkg.Type]map[candidateKey]candidateRemovals, ty pkg.Type, pkgName string) (vendors []string) {
|
||||||
|
removals, ok := allRemovals[ty]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if removal, ok := removals[candidateKey{
|
||||||
|
PkgName: pkgName,
|
||||||
|
}]; ok {
|
||||||
|
vendors = append(vendors, removal.VendorsToRemove...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return vendors
|
||||||
|
}
|
||||||
|
|
||||||
|
// findProductsToRemove searches all possible product removals that could be removed during the CPE generation process (given package info)
|
||||||
|
func findProductsToRemove(allRemovals map[pkg.Type]map[candidateKey]candidateRemovals, ty pkg.Type, pkgName string) (products []string) {
|
||||||
|
removals, ok := allRemovals[ty]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if removal, ok := removals[candidateKey{
|
||||||
|
PkgName: pkgName,
|
||||||
|
}]; ok {
|
||||||
|
products = append(products, removal.ProductsToRemove...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return products
|
||||||
|
}
|
||||||
|
|||||||
@ -154,3 +154,81 @@ func Test_additionalVendors(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_findVendorsToRemove(t *testing.T) {
|
||||||
|
//GIVEN
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
ty pkg.Type
|
||||||
|
pkgName string
|
||||||
|
expected []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "vendor removal match by input package name",
|
||||||
|
ty: pkg.JavaPkg,
|
||||||
|
pkgName: "my-package-name",
|
||||||
|
expected: []string{"awesome-vendor-addition"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "vendor removal miss by input package name",
|
||||||
|
ty: pkg.JavaPkg,
|
||||||
|
pkgName: "my-package-name-1",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
allRemovals := map[pkg.Type]map[candidateKey]candidateRemovals{
|
||||||
|
pkg.JavaPkg: {
|
||||||
|
candidateKey{
|
||||||
|
PkgName: "my-package-name",
|
||||||
|
}: {
|
||||||
|
VendorsToRemove: []string{"awesome-vendor-addition"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
//WHEN + THEN
|
||||||
|
assert.Equal(t, test.expected, findVendorsToRemove(allRemovals, test.ty, test.pkgName))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_findProductsToRemove(t *testing.T) {
|
||||||
|
//GIVEN
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
ty pkg.Type
|
||||||
|
pkgName string
|
||||||
|
expected []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "vendor removal match by input package name",
|
||||||
|
ty: pkg.JavaPkg,
|
||||||
|
pkgName: "my-package-name",
|
||||||
|
expected: []string{"awesome-vendor-addition"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "vendor removal miss by input package name",
|
||||||
|
ty: pkg.JavaPkg,
|
||||||
|
pkgName: "my-package-name-1",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
allRemovals := map[pkg.Type]map[candidateKey]candidateRemovals{
|
||||||
|
pkg.JavaPkg: {
|
||||||
|
candidateKey{
|
||||||
|
PkgName: "my-package-name",
|
||||||
|
}: {
|
||||||
|
ProductsToRemove: []string{"awesome-vendor-addition"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
//WHEN + THEN
|
||||||
|
assert.Equal(t, test.expected, findProductsToRemove(allRemovals, test.ty, test.pkgName))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -116,6 +116,9 @@ func candidateVendors(p pkg.Package) []string {
|
|||||||
vendors.addValue(findAdditionalVendors(defaultCandidateAdditions, p.Type, p.Name, vendor)...)
|
vendors.addValue(findAdditionalVendors(defaultCandidateAdditions, p.Type, p.Name, vendor)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// remove known mis
|
||||||
|
vendors.removeByValue(findVendorsToRemove(defaultCandidateRemovals, p.Type, p.Name)...)
|
||||||
|
|
||||||
return vendors.uniqueValues()
|
return vendors.uniqueValues()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,6 +151,9 @@ func candidateProducts(p pkg.Package) []string {
|
|||||||
// add known candidate additions
|
// add known candidate additions
|
||||||
products.addValue(findAdditionalProducts(defaultCandidateAdditions, p.Type, p.Name)...)
|
products.addValue(findAdditionalProducts(defaultCandidateAdditions, p.Type, p.Name)...)
|
||||||
|
|
||||||
|
// remove known candidate removals
|
||||||
|
products.removeByValue(findProductsToRemove(defaultCandidateRemovals, p.Type, p.Name)...)
|
||||||
|
|
||||||
return products.uniqueValues()
|
return products.uniqueValues()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -666,6 +666,27 @@ func TestGeneratePackageCPEs(t *testing.T) {
|
|||||||
"cpe:2.3:a:stephanie_morillo:bundler:2.1.4:*:*:*:*:*:*:*",
|
"cpe:2.3:a:stephanie_morillo:bundler:2.1.4:*:*:*:*:*:*:*",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "regression: python redis shadows normal redis",
|
||||||
|
p: pkg.Package{
|
||||||
|
Name: "redis",
|
||||||
|
Version: "2.1.4",
|
||||||
|
Type: pkg.PythonPkg,
|
||||||
|
FoundBy: "some-analyzer",
|
||||||
|
Language: pkg.Python,
|
||||||
|
},
|
||||||
|
expected: []string{
|
||||||
|
"cpe:2.3:a:python-redis:python-redis:2.1.4:*:*:*:*:*:*:*",
|
||||||
|
"cpe:2.3:a:python-redis:python_redis:2.1.4:*:*:*:*:*:*:*",
|
||||||
|
"cpe:2.3:a:python-redis:redis:2.1.4:*:*:*:*:*:*:*",
|
||||||
|
"cpe:2.3:a:python:python-redis:2.1.4:*:*:*:*:*:*:*",
|
||||||
|
"cpe:2.3:a:python:python_redis:2.1.4:*:*:*:*:*:*:*",
|
||||||
|
"cpe:2.3:a:python:redis:2.1.4:*:*:*:*:*:*:*",
|
||||||
|
"cpe:2.3:a:python_redis:python-redis:2.1.4:*:*:*:*:*:*:*",
|
||||||
|
"cpe:2.3:a:python_redis:python_redis:2.1.4:*:*:*:*:*:*:*",
|
||||||
|
"cpe:2.3:a:python_redis:redis:2.1.4:*:*:*:*:*:*:*",
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user