mirror of
https://github.com/anchore/grype
synced 2024-11-10 06:34:13 +00:00
fix: orient by cve merging (#1046)
This commit is contained in:
parent
3ff1d64eab
commit
04a84a4440
27 changed files with 319 additions and 294 deletions
2
go.mod
2
go.mod
|
@ -53,7 +53,7 @@ require (
|
|||
require (
|
||||
github.com/anchore/go-logger v0.0.0-20220728155337-03b66a5207d8
|
||||
github.com/anchore/sqlite v1.4.6-0.20220607210448-bcc6ee5c4963
|
||||
github.com/anchore/syft v0.64.0
|
||||
github.com/anchore/syft v0.65.0
|
||||
github.com/hako/durafmt v0.0.0-20210608085754-5c1018a4e16b
|
||||
github.com/in-toto/in-toto-golang v0.4.1-0.20221018183522-731d0640b65f
|
||||
github.com/mitchellh/mapstructure v1.5.0
|
||||
|
|
4
go.sum
4
go.sum
|
@ -240,8 +240,8 @@ github.com/anchore/sqlite v1.4.6-0.20220607210448-bcc6ee5c4963 h1:vrf2PYH77vqVJo
|
|||
github.com/anchore/sqlite v1.4.6-0.20220607210448-bcc6ee5c4963/go.mod h1:AVRyXOUP0hTz9Cb8OlD1XnwA8t4lBPfTuwPHmEUuiLc=
|
||||
github.com/anchore/stereoscope v0.0.0-20221208011002-c5ff155d72f1 h1:DXUAm/H9chRTEzMfkFyduBIcCiJyFXhCmv3zH3C0HGs=
|
||||
github.com/anchore/stereoscope v0.0.0-20221208011002-c5ff155d72f1/go.mod h1:/zjVnu2Jdl7xQCUtASegzeEg+IHKrM7SyMqdao3e+Nc=
|
||||
github.com/anchore/syft v0.64.0 h1:+hyo6Z34BLPZDDl//Bde5RiNhjN3wIT8AYlCiLAgLwg=
|
||||
github.com/anchore/syft v0.64.0/go.mod h1:jJu1mN1B602p4qS6sE28pAgcv5Xfx9h9M/jECMjIb6Q=
|
||||
github.com/anchore/syft v0.65.0 h1:w67aEZBeUSBZGiFy/u2wWwhbcq785xKl0tnvhsMlVm4=
|
||||
github.com/anchore/syft v0.65.0/go.mod h1:jJu1mN1B602p4qS6sE28pAgcv5Xfx9h9M/jECMjIb6Q=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
||||
github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||
github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||
|
|
|
@ -2,13 +2,13 @@ package cpe
|
|||
|
||||
import (
|
||||
"github.com/anchore/grype/internal/log"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/cpe"
|
||||
)
|
||||
|
||||
func NewSlice(cpeStrs ...string) ([]pkg.CPE, error) {
|
||||
var cpes []pkg.CPE
|
||||
func NewSlice(cpeStrs ...string) ([]cpe.CPE, error) {
|
||||
var cpes []cpe.CPE
|
||||
for _, c := range cpeStrs {
|
||||
value, err := pkg.NewCPE(c)
|
||||
value, err := cpe.New(c)
|
||||
if err != nil {
|
||||
log.Warnf("excluding invalid CPE %q: %v", c, err)
|
||||
continue
|
||||
|
@ -19,8 +19,8 @@ func NewSlice(cpeStrs ...string) ([]pkg.CPE, error) {
|
|||
return cpes, nil
|
||||
}
|
||||
|
||||
func MatchWithoutVersion(c pkg.CPE, candidates []pkg.CPE) []pkg.CPE {
|
||||
matches := make([]pkg.CPE, 0)
|
||||
func MatchWithoutVersion(c cpe.CPE, candidates []cpe.CPE) []cpe.CPE {
|
||||
matches := make([]cpe.CPE, 0)
|
||||
for _, candidate := range candidates {
|
||||
canCopy := candidate
|
||||
if c.MatchWithoutVersion(&canCopy) {
|
||||
|
|
|
@ -5,107 +5,100 @@ import (
|
|||
|
||||
"github.com/sergi/go-diff/diffmatchpatch"
|
||||
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/cpe"
|
||||
)
|
||||
|
||||
func must(c pkg.CPE, e error) pkg.CPE {
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func TestMatchWithoutVersion(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
compare pkg.CPE
|
||||
candidates []pkg.CPE
|
||||
expected []pkg.CPE
|
||||
compare cpe.CPE
|
||||
candidates []cpe.CPE
|
||||
expected []cpe.CPE
|
||||
}{
|
||||
{
|
||||
name: "GoCase",
|
||||
compare: must(pkg.NewCPE("cpe:2.3:*:python-requests:requests:2.3.0:*:*:*:*:python:*:*")),
|
||||
candidates: []pkg.CPE{
|
||||
must(pkg.NewCPE("cpe:2.3:a:python-requests:requests:2.2.1:*:*:*:*:*:*:*")),
|
||||
compare: cpe.Must("cpe:2.3:*:python-requests:requests:2.3.0:*:*:*:*:python:*:*"),
|
||||
candidates: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:a:python-requests:requests:2.2.1:*:*:*:*:*:*:*"),
|
||||
},
|
||||
expected: []pkg.CPE{
|
||||
must(pkg.NewCPE("cpe:2.3:a:python-requests:requests:2.2.1:*:*:*:*:*:*:*")),
|
||||
expected: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:a:python-requests:requests:2.2.1:*:*:*:*:*:*:*"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "IgnoreVersion",
|
||||
compare: must(pkg.NewCPE("cpe:2.3:*:name:name:3.2:*:*:*:*:java:*:*")),
|
||||
candidates: []pkg.CPE{
|
||||
must(pkg.NewCPE("cpe:2.3:*:name:name:3.2:*:*:*:*:java:*:*")),
|
||||
must(pkg.NewCPE("cpe:2.3:*:name:name:3.3:*:*:*:*:java:*:*")),
|
||||
must(pkg.NewCPE("cpe:2.3:*:name:name:5.5:*:*:*:*:java:*:*")),
|
||||
compare: cpe.Must("cpe:2.3:*:name:name:3.2:*:*:*:*:java:*:*"),
|
||||
candidates: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:name:name:3.2:*:*:*:*:java:*:*"),
|
||||
cpe.Must("cpe:2.3:*:name:name:3.3:*:*:*:*:java:*:*"),
|
||||
cpe.Must("cpe:2.3:*:name:name:5.5:*:*:*:*:java:*:*"),
|
||||
},
|
||||
expected: []pkg.CPE{
|
||||
must(pkg.NewCPE("cpe:2.3:*:name:name:3.2:*:*:*:*:java:*:*")),
|
||||
must(pkg.NewCPE("cpe:2.3:*:name:name:3.3:*:*:*:*:java:*:*")),
|
||||
must(pkg.NewCPE("cpe:2.3:*:name:name:5.5:*:*:*:*:java:*:*")),
|
||||
expected: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:name:name:3.2:*:*:*:*:java:*:*"),
|
||||
cpe.Must("cpe:2.3:*:name:name:3.3:*:*:*:*:java:*:*"),
|
||||
cpe.Must("cpe:2.3:*:name:name:5.5:*:*:*:*:java:*:*"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MatchByTargetSW",
|
||||
compare: must(pkg.NewCPE("cpe:2.3:*:name:name:3.2:*:*:*:*:java:*:*")),
|
||||
candidates: []pkg.CPE{
|
||||
must(pkg.NewCPE("cpe:2.3:*:name:name:3.2:*:*:*:*:java:*:*")),
|
||||
must(pkg.NewCPE("cpe:2.3:*:name:name:3.2:*:*:*:*:maven:*:*")),
|
||||
must(pkg.NewCPE("cpe:2.3:*:name:name:3.2:*:*:*:*:jenkins:*:*")),
|
||||
must(pkg.NewCPE("cpe:2.3:*:name:name:3.2:*:*:*:*:cloudbees_jenkins:*:*")),
|
||||
must(pkg.NewCPE("cpe:2.3:*:name:name:3.2:*:*:*:*:*:*:*")),
|
||||
compare: cpe.Must("cpe:2.3:*:name:name:3.2:*:*:*:*:java:*:*"),
|
||||
candidates: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:name:name:3.2:*:*:*:*:java:*:*"),
|
||||
cpe.Must("cpe:2.3:*:name:name:3.2:*:*:*:*:maven:*:*"),
|
||||
cpe.Must("cpe:2.3:*:name:name:3.2:*:*:*:*:jenkins:*:*"),
|
||||
cpe.Must("cpe:2.3:*:name:name:3.2:*:*:*:*:cloudbees_jenkins:*:*"),
|
||||
cpe.Must("cpe:2.3:*:name:name:3.2:*:*:*:*:*:*:*"),
|
||||
},
|
||||
expected: []pkg.CPE{
|
||||
must(pkg.NewCPE("cpe:2.3:*:name:name:3.2:*:*:*:*:java:*:*")),
|
||||
must(pkg.NewCPE("cpe:2.3:*:name:name:3.2:*:*:*:*:*:*:*")),
|
||||
expected: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:name:name:3.2:*:*:*:*:java:*:*"),
|
||||
cpe.Must("cpe:2.3:*:name:name:3.2:*:*:*:*:*:*:*"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MatchByName",
|
||||
compare: must(pkg.NewCPE("cpe:2.3:*:name:name5:3.2:*:*:*:*:java:*:*")),
|
||||
candidates: []pkg.CPE{
|
||||
must(pkg.NewCPE("cpe:2.3:*:name:name1:3.2:*:*:*:*:java:*:*")),
|
||||
must(pkg.NewCPE("cpe:2.3:*:name:name2:3.2:*:*:*:*:java:*:*")),
|
||||
must(pkg.NewCPE("cpe:2.3:*:name:name3:3.2:*:*:*:*:java:*:*")),
|
||||
must(pkg.NewCPE("cpe:2.3:*:name:name4:3.2:*:*:*:*:java:*:*")),
|
||||
must(pkg.NewCPE("cpe:2.3:*:name:name5:3.2:*:*:*:*:*:*:*")),
|
||||
compare: cpe.Must("cpe:2.3:*:name:name5:3.2:*:*:*:*:java:*:*"),
|
||||
candidates: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:name:name1:3.2:*:*:*:*:java:*:*"),
|
||||
cpe.Must("cpe:2.3:*:name:name2:3.2:*:*:*:*:java:*:*"),
|
||||
cpe.Must("cpe:2.3:*:name:name3:3.2:*:*:*:*:java:*:*"),
|
||||
cpe.Must("cpe:2.3:*:name:name4:3.2:*:*:*:*:java:*:*"),
|
||||
cpe.Must("cpe:2.3:*:name:name5:3.2:*:*:*:*:*:*:*"),
|
||||
},
|
||||
expected: []pkg.CPE{
|
||||
must(pkg.NewCPE("cpe:2.3:*:name:name5:3.2:*:*:*:*:*:*:*")),
|
||||
expected: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:name:name5:3.2:*:*:*:*:*:*:*"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MatchByVendor",
|
||||
compare: must(pkg.NewCPE("cpe:2.3:*:name3:name:3.2:*:*:*:*:java:*:*")),
|
||||
candidates: []pkg.CPE{
|
||||
must(pkg.NewCPE("cpe:2.3:*:name1:name:3.2:*:*:*:*:java:*:*")),
|
||||
must(pkg.NewCPE("cpe:2.3:*:name3:name:3.2:*:*:*:*:jaba-no-bother:*:*")),
|
||||
must(pkg.NewCPE("cpe:2.3:*:name3:name:3.2:*:*:*:*:java:*:*")),
|
||||
must(pkg.NewCPE("cpe:2.3:*:name4:name:3.2:*:*:*:*:java:*:*")),
|
||||
must(pkg.NewCPE("cpe:2.3:*:name5:name:3.2:*:*:*:*:*:*:*")),
|
||||
compare: cpe.Must("cpe:2.3:*:name3:name:3.2:*:*:*:*:java:*:*"),
|
||||
candidates: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:name1:name:3.2:*:*:*:*:java:*:*"),
|
||||
cpe.Must("cpe:2.3:*:name3:name:3.2:*:*:*:*:jaba-no-bother:*:*"),
|
||||
cpe.Must("cpe:2.3:*:name3:name:3.2:*:*:*:*:java:*:*"),
|
||||
cpe.Must("cpe:2.3:*:name4:name:3.2:*:*:*:*:java:*:*"),
|
||||
cpe.Must("cpe:2.3:*:name5:name:3.2:*:*:*:*:*:*:*"),
|
||||
},
|
||||
expected: []pkg.CPE{
|
||||
must(pkg.NewCPE("cpe:2.3:*:name3:name:3.2:*:*:*:*:java:*:*")),
|
||||
expected: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:name3:name:3.2:*:*:*:*:java:*:*"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MatchAnyVendorOrTargetSW",
|
||||
compare: must(pkg.NewCPE("cpe:2.3:*:*:name:3.2:*:*:*:*:*:*:*")),
|
||||
candidates: []pkg.CPE{
|
||||
must(pkg.NewCPE("cpe:2.3:*:name1:name:3.2:*:*:*:*:java:*:*")),
|
||||
must(pkg.NewCPE("cpe:2.3:*:name3:name:3.2:*:*:*:*:jaba-no-bother:*:*")),
|
||||
must(pkg.NewCPE("cpe:2.3:*:name3:name:3.2:*:*:*:*:java:*:*")),
|
||||
must(pkg.NewCPE("cpe:2.3:*:name4:name:3.2:*:*:*:*:java:*:*")),
|
||||
must(pkg.NewCPE("cpe:2.3:*:name5:name:3.2:*:*:*:*:*:*:*")),
|
||||
must(pkg.NewCPE("cpe:2.3:*:name5:NOMATCH:3.2:*:*:*:*:*:*:*")),
|
||||
compare: cpe.Must("cpe:2.3:*:*:name:3.2:*:*:*:*:*:*:*"),
|
||||
candidates: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:name1:name:3.2:*:*:*:*:java:*:*"),
|
||||
cpe.Must("cpe:2.3:*:name3:name:3.2:*:*:*:*:jaba-no-bother:*:*"),
|
||||
cpe.Must("cpe:2.3:*:name3:name:3.2:*:*:*:*:java:*:*"),
|
||||
cpe.Must("cpe:2.3:*:name4:name:3.2:*:*:*:*:java:*:*"),
|
||||
cpe.Must("cpe:2.3:*:name5:name:3.2:*:*:*:*:*:*:*"),
|
||||
cpe.Must("cpe:2.3:*:name5:NOMATCH:3.2:*:*:*:*:*:*:*"),
|
||||
},
|
||||
expected: []pkg.CPE{
|
||||
must(pkg.NewCPE("cpe:2.3:*:name1:name:3.2:*:*:*:*:java:*:*")),
|
||||
must(pkg.NewCPE("cpe:2.3:*:name3:name:3.2:*:*:*:*:jaba-no-bother:*:*")),
|
||||
must(pkg.NewCPE("cpe:2.3:*:name3:name:3.2:*:*:*:*:java:*:*")),
|
||||
must(pkg.NewCPE("cpe:2.3:*:name4:name:3.2:*:*:*:*:java:*:*")),
|
||||
must(pkg.NewCPE("cpe:2.3:*:name5:name:3.2:*:*:*:*:*:*:*")),
|
||||
expected: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:name1:name:3.2:*:*:*:*:java:*:*"),
|
||||
cpe.Must("cpe:2.3:*:name3:name:3.2:*:*:*:*:jaba-no-bother:*:*"),
|
||||
cpe.Must("cpe:2.3:*:name3:name:3.2:*:*:*:*:java:*:*"),
|
||||
cpe.Must("cpe:2.3:*:name4:name:3.2:*:*:*:*:java:*:*"),
|
||||
cpe.Must("cpe:2.3:*:name5:name:3.2:*:*:*:*:*:*:*"),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -5,13 +5,14 @@ import (
|
|||
|
||||
"github.com/facebookincubator/nvdtools/wfn"
|
||||
|
||||
"github.com/anchore/grype/grype/cpe"
|
||||
cpeUtil "github.com/anchore/grype/grype/cpe"
|
||||
grypeDB "github.com/anchore/grype/grype/db/v5"
|
||||
"github.com/anchore/grype/grype/db/v5/namespace"
|
||||
"github.com/anchore/grype/grype/distro"
|
||||
"github.com/anchore/grype/grype/pkg"
|
||||
"github.com/anchore/grype/grype/vulnerability"
|
||||
"github.com/anchore/grype/internal/log"
|
||||
"github.com/anchore/syft/syft/cpe"
|
||||
syftPkg "github.com/anchore/syft/syft/pkg"
|
||||
)
|
||||
|
||||
|
@ -131,7 +132,7 @@ func (pr *VulnerabilityProvider) GetByLanguage(l syftPkg.Language, p pkg.Package
|
|||
return vulnerabilities, nil
|
||||
}
|
||||
|
||||
func (pr *VulnerabilityProvider) GetByCPE(requestCPE syftPkg.CPE) ([]vulnerability.Vulnerability, error) {
|
||||
func (pr *VulnerabilityProvider) GetByCPE(requestCPE cpe.CPE) ([]vulnerability.Vulnerability, error) {
|
||||
vulns := make([]vulnerability.Vulnerability, 0)
|
||||
namespaces := pr.namespaceIndex.CPENamespaces()
|
||||
|
||||
|
@ -150,20 +151,20 @@ func (pr *VulnerabilityProvider) GetByCPE(requestCPE syftPkg.CPE) ([]vulnerabili
|
|||
return nil, fmt.Errorf("provider failed to fetch namespace=%q product=%q: %w", ns, requestCPE.Product, err)
|
||||
}
|
||||
|
||||
normalizedRequestCPE, err := syftPkg.NewCPE(ns.Resolver().Normalize(requestCPE.BindToFmtString()))
|
||||
normalizedRequestCPE, err := cpe.New(ns.Resolver().Normalize(requestCPE.BindToFmtString()))
|
||||
|
||||
if err != nil {
|
||||
normalizedRequestCPE = requestCPE
|
||||
}
|
||||
|
||||
for _, vuln := range allPkgVulns {
|
||||
vulnCPEs, err := cpe.NewSlice(vuln.CPEs...)
|
||||
vulnCPEs, err := cpeUtil.NewSlice(vuln.CPEs...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// compare the request CPE to the potential matches (excluding version, which is handled downstream)
|
||||
candidateMatchCpes := cpe.MatchWithoutVersion(normalizedRequestCPE, vulnCPEs)
|
||||
candidateMatchCpes := cpeUtil.MatchWithoutVersion(normalizedRequestCPE, vulnCPEs)
|
||||
|
||||
if len(candidateMatchCpes) > 0 {
|
||||
vulnObj, err := vulnerability.NewVulnerability(vuln)
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
"github.com/anchore/grype/grype/pkg/qualifier"
|
||||
"github.com/anchore/grype/grype/version"
|
||||
"github.com/anchore/grype/grype/vulnerability"
|
||||
syftPkg "github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/cpe"
|
||||
)
|
||||
|
||||
func Test_GetByDistro(t *testing.T) {
|
||||
|
@ -37,7 +37,7 @@ func Test_GetByDistro(t *testing.T) {
|
|||
ID: "CVE-2014-fake-1",
|
||||
Namespace: "debian:distro:debian:8",
|
||||
PackageQualifiers: []qualifier.Qualifier{},
|
||||
CPEs: []syftPkg.CPE{},
|
||||
CPEs: []cpe.CPE{},
|
||||
Advisories: []vulnerability.Advisory{},
|
||||
},
|
||||
{
|
||||
|
@ -45,7 +45,7 @@ func Test_GetByDistro(t *testing.T) {
|
|||
ID: "CVE-2013-fake-2",
|
||||
Namespace: "debian:distro:debian:8",
|
||||
PackageQualifiers: []qualifier.Qualifier{},
|
||||
CPEs: []syftPkg.CPE{},
|
||||
CPEs: []cpe.CPE{},
|
||||
Advisories: []vulnerability.Advisory{},
|
||||
},
|
||||
}
|
||||
|
@ -74,30 +74,23 @@ func Test_GetByDistro_nilDistro(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func must(c syftPkg.CPE, e error) syftPkg.CPE {
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func Test_GetByCPE(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
cpe syftPkg.CPE
|
||||
cpe cpe.CPE
|
||||
expected []vulnerability.Vulnerability
|
||||
err bool
|
||||
}{
|
||||
{
|
||||
name: "match from name and target SW",
|
||||
cpe: must(syftPkg.NewCPE("cpe:2.3:*:activerecord:activerecord:*:*:*:*:*:ruby:*:*")),
|
||||
cpe: cpe.Must("cpe:2.3:*:activerecord:activerecord:*:*:*:*:*:ruby:*:*"),
|
||||
expected: []vulnerability.Vulnerability{
|
||||
{
|
||||
Constraint: version.MustGetConstraint("< 3.7.4", version.UnknownFormat),
|
||||
ID: "CVE-2014-fake-4",
|
||||
CPEs: []syftPkg.CPE{
|
||||
must(syftPkg.NewCPE("cpe:2.3:*:activerecord:activerecord:*:*:something:*:*:ruby:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:activerecord:activerecord:*:*:something:*:*:ruby:*:*"),
|
||||
},
|
||||
Namespace: "nvd:cpe",
|
||||
PackageQualifiers: []qualifier.Qualifier{},
|
||||
|
@ -107,13 +100,13 @@ func Test_GetByCPE(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "match with normalization",
|
||||
cpe: must(syftPkg.NewCPE("cpe:2.3:*:ActiVERecord:ACTiveRecord:*:*:*:*:*:ruby:*:*")),
|
||||
cpe: cpe.Must("cpe:2.3:*:ActiVERecord:ACTiveRecord:*:*:*:*:*:ruby:*:*"),
|
||||
expected: []vulnerability.Vulnerability{
|
||||
{
|
||||
Constraint: version.MustGetConstraint("< 3.7.4", version.UnknownFormat),
|
||||
ID: "CVE-2014-fake-4",
|
||||
CPEs: []syftPkg.CPE{
|
||||
must(syftPkg.NewCPE("cpe:2.3:*:activerecord:activerecord:*:*:something:*:*:ruby:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:activerecord:activerecord:*:*:something:*:*:ruby:*:*"),
|
||||
},
|
||||
Namespace: "nvd:cpe",
|
||||
PackageQualifiers: []qualifier.Qualifier{},
|
||||
|
@ -123,13 +116,13 @@ func Test_GetByCPE(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "match from vendor & name",
|
||||
cpe: must(syftPkg.NewCPE("cpe:2.3:*:activerecord:activerecord:*:*:*:*:*:*:*:*")),
|
||||
cpe: cpe.Must("cpe:2.3:*:activerecord:activerecord:*:*:*:*:*:*:*:*"),
|
||||
expected: []vulnerability.Vulnerability{
|
||||
{
|
||||
Constraint: version.MustGetConstraint("< 3.7.6", version.UnknownFormat),
|
||||
ID: "CVE-2014-fake-3",
|
||||
CPEs: []syftPkg.CPE{
|
||||
must(syftPkg.NewCPE("cpe:2.3:*:activerecord:activerecord:*:*:*:*:*:rails:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:activerecord:activerecord:*:*:*:*:*:rails:*:*"),
|
||||
},
|
||||
Namespace: "nvd:cpe",
|
||||
PackageQualifiers: []qualifier.Qualifier{},
|
||||
|
@ -138,8 +131,8 @@ func Test_GetByCPE(t *testing.T) {
|
|||
{
|
||||
Constraint: version.MustGetConstraint("< 3.7.4", version.UnknownFormat),
|
||||
ID: "CVE-2014-fake-4",
|
||||
CPEs: []syftPkg.CPE{
|
||||
must(syftPkg.NewCPE("cpe:2.3:*:activerecord:activerecord:*:*:something:*:*:ruby:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:activerecord:activerecord:*:*:something:*:*:ruby:*:*"),
|
||||
},
|
||||
Namespace: "nvd:cpe",
|
||||
PackageQualifiers: []qualifier.Qualifier{},
|
||||
|
@ -150,7 +143,7 @@ func Test_GetByCPE(t *testing.T) {
|
|||
|
||||
{
|
||||
name: "dont allow any name",
|
||||
cpe: must(syftPkg.NewCPE("cpe:2.3:*:couldntgetthisrightcouldyou:*:*:*:*:*:*:*:*:*")),
|
||||
cpe: cpe.Must("cpe:2.3:*:couldntgetthisrightcouldyou:*:*:*:*:*:*:*:*:*"),
|
||||
err: true,
|
||||
},
|
||||
}
|
||||
|
@ -193,7 +186,7 @@ func Test_Get(t *testing.T) {
|
|||
ID: "CVE-2014-fake-1",
|
||||
Namespace: "debian:distro:debian:8",
|
||||
PackageQualifiers: []qualifier.Qualifier{},
|
||||
CPEs: []syftPkg.CPE{},
|
||||
CPEs: []cpe.CPE{},
|
||||
Advisories: []vulnerability.Advisory{},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -2,12 +2,14 @@ package match
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/scylladb/go-set/strset"
|
||||
|
||||
"github.com/anchore/grype/grype/pkg"
|
||||
"github.com/anchore/grype/grype/vulnerability"
|
||||
"github.com/anchore/syft/syft/cpe"
|
||||
)
|
||||
|
||||
var ErrCannotMerge = fmt.Errorf("unable to merge vulnerability matches")
|
||||
|
@ -42,17 +44,56 @@ func (m *Match) Merge(other Match) error {
|
|||
return ErrCannotMerge
|
||||
}
|
||||
|
||||
// there are cases related vulnerabilities are synthetic, for example when
|
||||
// orienting results by CVE. we need to keep track of these
|
||||
related := strset.New()
|
||||
for _, r := range m.Vulnerability.RelatedVulnerabilities {
|
||||
related.Add(referenceID(r))
|
||||
}
|
||||
for _, r := range other.Vulnerability.RelatedVulnerabilities {
|
||||
if related.Has(referenceID(r)) {
|
||||
continue
|
||||
}
|
||||
m.Vulnerability.RelatedVulnerabilities = append(m.Vulnerability.RelatedVulnerabilities, r)
|
||||
}
|
||||
|
||||
// for stable output
|
||||
sort.Slice(m.Vulnerability.RelatedVulnerabilities, func(i, j int) bool {
|
||||
a := m.Vulnerability.RelatedVulnerabilities[i]
|
||||
b := m.Vulnerability.RelatedVulnerabilities[j]
|
||||
return strings.Compare(referenceID(a), referenceID(b)) < 0
|
||||
})
|
||||
|
||||
// also keep details from the other match that are unique
|
||||
detailIDs := strset.New()
|
||||
for _, d := range m.Details {
|
||||
detailIDs.Add(d.ID())
|
||||
}
|
||||
|
||||
// keep details from the other match that are unique
|
||||
for _, d := range other.Details {
|
||||
if detailIDs.Has(d.ID()) {
|
||||
continue
|
||||
}
|
||||
m.Details = append(m.Details, d)
|
||||
}
|
||||
|
||||
// for stable output
|
||||
sort.Slice(m.Details, func(i, j int) bool {
|
||||
a := m.Details[i]
|
||||
b := m.Details[j]
|
||||
return strings.Compare(a.ID(), b.ID()) < 0
|
||||
})
|
||||
|
||||
// retain all unique CPEs for consistent output
|
||||
m.Vulnerability.CPEs = cpe.Merge(m.Vulnerability.CPEs, other.Vulnerability.CPEs)
|
||||
if m.Vulnerability.CPEs == nil {
|
||||
// ensure we always have a non-nil slice
|
||||
m.Vulnerability.CPEs = []cpe.CPE{}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// referenceID returns an "ID" string for a vulnerability.Reference
|
||||
func referenceID(r vulnerability.Reference) string {
|
||||
return fmt.Sprintf("%s:%s", r.Namespace, r.ID)
|
||||
}
|
||||
|
|
|
@ -16,16 +16,10 @@ import (
|
|||
"github.com/anchore/grype/grype/pkg"
|
||||
"github.com/anchore/grype/grype/search"
|
||||
"github.com/anchore/grype/grype/vulnerability"
|
||||
"github.com/anchore/syft/syft/cpe"
|
||||
syftPkg "github.com/anchore/syft/syft/pkg"
|
||||
)
|
||||
|
||||
func must(c syftPkg.CPE, e error) syftPkg.CPE {
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
type mockStore struct {
|
||||
backend map[string]map[string][]grypeDB.Vulnerability
|
||||
}
|
||||
|
@ -87,8 +81,8 @@ func TestSecDBOnlyMatch(t *testing.T) {
|
|||
Name: "libvncserver",
|
||||
Version: "0.9.9",
|
||||
Type: syftPkg.ApkPkg,
|
||||
CPEs: []syftPkg.CPE{
|
||||
must(syftPkg.NewCPE("cpe:2.3:a:*:libvncserver:0.9.9:*:*:*:*:*:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:a:*:libvncserver:0.9.9:*:*:*:*:*:*:*"),
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -173,8 +167,8 @@ func TestBothSecdbAndNvdMatches(t *testing.T) {
|
|||
Name: "libvncserver",
|
||||
Version: "0.9.9",
|
||||
Type: syftPkg.ApkPkg,
|
||||
CPEs: []syftPkg.CPE{
|
||||
must(syftPkg.NewCPE("cpe:2.3:a:*:libvncserver:0.9.9:*:*:*:*:*:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:a:*:libvncserver:0.9.9:*:*:*:*:*:*:*"),
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -260,9 +254,9 @@ func TestBothSecdbAndNvdMatches_DifferentPackageName(t *testing.T) {
|
|||
Name: "libvncserver",
|
||||
Version: "0.9.9",
|
||||
Type: syftPkg.ApkPkg,
|
||||
CPEs: []syftPkg.CPE{
|
||||
CPEs: []cpe.CPE{
|
||||
// Note: the product name is NOT the same as the package name
|
||||
must(syftPkg.NewCPE("cpe:2.3:a:*:libvncumbrellaproject:0.9.9:*:*:*:*:*:*:*")),
|
||||
cpe.Must("cpe:2.3:a:*:libvncumbrellaproject:0.9.9:*:*:*:*:*:*:*"),
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -335,14 +329,14 @@ func TestNvdOnlyMatches(t *testing.T) {
|
|||
Name: "libvncserver",
|
||||
Version: "0.9.9",
|
||||
Type: syftPkg.ApkPkg,
|
||||
CPEs: []syftPkg.CPE{
|
||||
must(syftPkg.NewCPE("cpe:2.3:a:*:libvncserver:0.9.9:*:*:*:*:*:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:a:*:libvncserver:0.9.9:*:*:*:*:*:*:*"),
|
||||
},
|
||||
}
|
||||
|
||||
vulnFound, err := vulnerability.NewVulnerability(nvdVuln)
|
||||
assert.NoError(t, err)
|
||||
vulnFound.CPEs = []syftPkg.CPE{must(syftPkg.NewCPE(nvdVuln.CPEs[0]))}
|
||||
vulnFound.CPEs = []cpe.CPE{cpe.Must(nvdVuln.CPEs[0])}
|
||||
|
||||
expected := []match.Match{
|
||||
{
|
||||
|
@ -413,8 +407,8 @@ func TestNvdMatchesWithSecDBFix(t *testing.T) {
|
|||
Name: "libvncserver",
|
||||
Version: "0.9.11",
|
||||
Type: syftPkg.ApkPkg,
|
||||
CPEs: []syftPkg.CPE{
|
||||
must(syftPkg.NewCPE("cpe:2.3:a:*:libvncserver:0.9.9:*:*:*:*:*:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:a:*:libvncserver:0.9.9:*:*:*:*:*:*:*"),
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -466,8 +460,8 @@ func TestNvdMatchesNoConstraintWithSecDBFix(t *testing.T) {
|
|||
Name: "libvncserver",
|
||||
Version: "0.9.11",
|
||||
Type: syftPkg.ApkPkg,
|
||||
CPEs: []syftPkg.CPE{
|
||||
must(syftPkg.NewCPE("cpe:2.3:a:*:libvncserver:0.9.9:*:*:*:*:*:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:a:*:libvncserver:0.9.9:*:*:*:*:*:*:*"),
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -584,9 +578,9 @@ func TestNVDMatchBySourceIndirection(t *testing.T) {
|
|||
Name: "musl-utils",
|
||||
Version: "1.3.2-r0",
|
||||
Type: syftPkg.ApkPkg,
|
||||
CPEs: []syftPkg.CPE{
|
||||
must(syftPkg.NewCPE("cpe:2.3:a:musl-utils:musl-utils:*:*:*:*:*:*:*:*")),
|
||||
must(syftPkg.NewCPE("cpe:2.3:a:musl-utils:musl-utils:*:*:*:*:*:*:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:a:musl-utils:musl-utils:*:*:*:*:*:*:*:*"),
|
||||
cpe.Must("cpe:2.3:a:musl-utils:musl-utils:*:*:*:*:*:*:*:*"),
|
||||
},
|
||||
Upstreams: []pkg.UpstreamPackage{
|
||||
{
|
||||
|
@ -597,7 +591,7 @@ func TestNVDMatchBySourceIndirection(t *testing.T) {
|
|||
|
||||
vulnFound, err := vulnerability.NewVulnerability(nvdVuln)
|
||||
assert.NoError(t, err)
|
||||
vulnFound.CPEs = []syftPkg.CPE{must(syftPkg.NewCPE(nvdVuln.CPEs[0]))}
|
||||
vulnFound.CPEs = []cpe.CPE{cpe.Must(nvdVuln.CPEs[0])}
|
||||
|
||||
expected := []match.Match{
|
||||
{
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/anchore/grype/grype/pkg"
|
||||
"github.com/anchore/grype/grype/version"
|
||||
"github.com/anchore/grype/grype/vulnerability"
|
||||
"github.com/anchore/syft/syft/cpe"
|
||||
syftPkg "github.com/anchore/syft/syft/pkg"
|
||||
)
|
||||
|
||||
|
@ -62,7 +63,7 @@ func (mp *mockProvider) populateData() {
|
|||
}
|
||||
}
|
||||
|
||||
func (mp *mockProvider) GetByCPE(p syftPkg.CPE) ([]vulnerability.Vulnerability, error) {
|
||||
func (mp *mockProvider) GetByCPE(p cpe.CPE) ([]vulnerability.Vulnerability, error) {
|
||||
return []vulnerability.Vulnerability{}, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"github.com/anchore/grype/grype/pkg"
|
||||
"github.com/anchore/grype/grype/version"
|
||||
"github.com/anchore/grype/grype/vulnerability"
|
||||
"github.com/anchore/syft/syft/cpe"
|
||||
syftPkg "github.com/anchore/syft/syft/pkg"
|
||||
)
|
||||
|
||||
|
@ -61,7 +62,7 @@ func newMockSearcher(pkg pkg.Package) MavenSearcher {
|
|||
}
|
||||
}
|
||||
|
||||
func (mp *mockProvider) GetByCPE(p syftPkg.CPE) ([]vulnerability.Vulnerability, error) {
|
||||
func (mp *mockProvider) GetByCPE(p cpe.CPE) ([]vulnerability.Vulnerability, error) {
|
||||
return []vulnerability.Vulnerability{}, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"github.com/anchore/grype/grype/pkg"
|
||||
"github.com/anchore/grype/grype/version"
|
||||
"github.com/anchore/grype/grype/vulnerability"
|
||||
"github.com/anchore/syft/syft/cpe"
|
||||
syftPkg "github.com/anchore/syft/syft/pkg"
|
||||
)
|
||||
|
||||
|
@ -47,7 +48,7 @@ func (pr *mockProvider) GetByDistro(d *distro.Distro, p pkg.Package) ([]vulnerab
|
|||
return pr.data[strings.ToLower(d.Type.String())+":"+d.FullVersion()][p.Name], nil
|
||||
}
|
||||
|
||||
func (pr *mockProvider) GetByCPE(request syftPkg.CPE) (v []vulnerability.Vulnerability, err error) {
|
||||
func (pr *mockProvider) GetByCPE(request cpe.CPE) (v []vulnerability.Vulnerability, err error) {
|
||||
return v, err
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/anchore/grype/grype/pkg/qualifier/rpmmodularity"
|
||||
"github.com/anchore/grype/grype/version"
|
||||
"github.com/anchore/grype/grype/vulnerability"
|
||||
"github.com/anchore/syft/syft/cpe"
|
||||
syftPkg "github.com/anchore/syft/syft/pkg"
|
||||
)
|
||||
|
||||
|
@ -135,7 +136,7 @@ func (pr *mockProvider) GetByDistro(d *distro.Distro, p pkg.Package) ([]vulnerab
|
|||
return pr.data[ty+":"+d.FullVersion()][p.Name], nil
|
||||
}
|
||||
|
||||
func (pr *mockProvider) GetByCPE(request syftPkg.CPE) (v []vulnerability.Vulnerability, err error) {
|
||||
func (pr *mockProvider) GetByCPE(request cpe.CPE) (v []vulnerability.Vulnerability, err error) {
|
||||
return v, err
|
||||
}
|
||||
|
||||
|
|
|
@ -8,8 +8,9 @@ import (
|
|||
"github.com/anchore/grype/internal"
|
||||
"github.com/anchore/grype/internal/log"
|
||||
"github.com/anchore/syft/syft/artifact"
|
||||
"github.com/anchore/syft/syft/cpe"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/common/cpe"
|
||||
cpes "github.com/anchore/syft/syft/pkg/cataloger/common/cpe"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
)
|
||||
|
||||
|
@ -34,7 +35,7 @@ type Package struct {
|
|||
Language pkg.Language // the language ecosystem this package belongs to (e.g. JavaScript, Python, etc)
|
||||
Licenses []string
|
||||
Type pkg.Type // the package type (e.g. Npm, Yarn, Python, Rpm, Deb, etc)
|
||||
CPEs []pkg.CPE // all possible Common Platform Enumerators
|
||||
CPEs []cpe.CPE // all possible Common Platform Enumerators
|
||||
PURL string // the Package URL (see https://github.com/package-url/purl-spec)
|
||||
Upstreams []UpstreamPackage
|
||||
MetadataType MetadataType
|
||||
|
@ -71,7 +72,7 @@ func FromPackages(syftpkgs []pkg.Package, config SynthesisConfig) []Package {
|
|||
if len(p.CPEs) == 0 {
|
||||
// For SPDX (or any format, really) we may have no CPEs
|
||||
if config.GenerateMissingCPEs {
|
||||
p.CPEs = cpe.Generate(p)
|
||||
p.CPEs = cpes.Generate(p)
|
||||
} else {
|
||||
log.Debugf("no CPEs for package: %s", p)
|
||||
missingCPEs = true
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/anchore/syft/syft/artifact"
|
||||
"github.com/anchore/syft/syft/cpe"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
syftFile "github.com/anchore/syft/syft/file"
|
||||
syftPkg "github.com/anchore/syft/syft/pkg"
|
||||
|
@ -428,7 +429,7 @@ func TestFromCatalog_GeneratesCPEs(t *testing.T) {
|
|||
catalog.Add(syftPkg.Package{
|
||||
Name: "first",
|
||||
Version: "1",
|
||||
CPEs: []syftPkg.CPE{
|
||||
CPEs: []cpe.CPE{
|
||||
{},
|
||||
},
|
||||
})
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/mitchellh/go-homedir"
|
||||
|
||||
"github.com/anchore/packageurl-go"
|
||||
"github.com/anchore/syft/syft/cpe"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
)
|
||||
|
||||
|
@ -57,11 +58,11 @@ func decodePurlFile(reader io.Reader) ([]Package, error) {
|
|||
if qualifier.Key == cpesQualifierKey {
|
||||
rawCpes := strings.Split(qualifier.Value, ",")
|
||||
for _, rawCpe := range rawCpes {
|
||||
cpe, err := pkg.NewCPE(rawCpe)
|
||||
c, err := cpe.New(rawCpe)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to decode cpe %s in purl %s: %w", rawCpe, rawLine, err)
|
||||
}
|
||||
cpes = append(cpes, cpe)
|
||||
cpes = append(cpes, c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,18 +11,11 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/anchore/syft/syft"
|
||||
"github.com/anchore/syft/syft/cpe"
|
||||
"github.com/anchore/syft/syft/linux"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
)
|
||||
|
||||
func must(c pkg.CPE, e error) pkg.CPE {
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func assertAs(expected string) assert.ErrorAssertionFunc {
|
||||
return func(t assert.TestingT, err error, i ...interface{}) bool {
|
||||
return assert.ErrorContains(t, errors.New(expected), err.Error())
|
||||
|
@ -228,8 +221,8 @@ func TestParseSyftJSON(t *testing.T) {
|
|||
"GPL-2.0-only",
|
||||
},
|
||||
Type: "apk",
|
||||
CPEs: []pkg.CPE{
|
||||
must(pkg.NewCPE("cpe:2.3:a:alpine:alpine_baselayout:3.2.0-r6:*:*:*:*:*:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:a:alpine:alpine_baselayout:3.2.0-r6:*:*:*:*:*:*:*"),
|
||||
},
|
||||
PURL: "pkg:alpine/alpine-baselayout@3.2.0-r6?arch=x86_64",
|
||||
Upstreams: []UpstreamPackage{
|
||||
|
@ -252,9 +245,9 @@ func TestParseSyftJSON(t *testing.T) {
|
|||
"LGPL-3.0-or-later",
|
||||
},
|
||||
Type: "dpkg",
|
||||
CPEs: []pkg.CPE{
|
||||
must(pkg.NewCPE("cpe:2.3:a:*:fake:1.2.0:*:*:*:*:*:*:*")),
|
||||
must(pkg.NewCPE("cpe:2.3:a:fake:fake:1.2.0:*:*:*:*:*:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:a:*:fake:1.2.0:*:*:*:*:*:*:*"),
|
||||
cpe.Must("cpe:2.3:a:fake:fake:1.2.0:*:*:*:*:*:*:*"),
|
||||
},
|
||||
PURL: "pkg:deb/debian/fake@1.2.0?arch=x86_64",
|
||||
Upstreams: []UpstreamPackage{
|
||||
|
@ -278,9 +271,9 @@ func TestParseSyftJSON(t *testing.T) {
|
|||
"LGPL-3.0-or-later",
|
||||
},
|
||||
Type: "java-archive",
|
||||
CPEs: []pkg.CPE{
|
||||
must(pkg.NewCPE("cpe:2.3:a:*:gmp:6.2.0-r0:*:*:*:*:*:*:*")),
|
||||
must(pkg.NewCPE("cpe:2.3:a:gmp:gmp:6.2.0-r0:*:*:*:*:*:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:a:*:gmp:6.2.0-r0:*:*:*:*:*:*:*"),
|
||||
cpe.Must("cpe:2.3:a:gmp:gmp:6.2.0-r0:*:*:*:*:*:*:*"),
|
||||
},
|
||||
PURL: "pkg:alpine/gmp@6.2.0-r0?arch=x86_64",
|
||||
MetadataType: JavaMetadataType,
|
||||
|
@ -379,9 +372,9 @@ var springImageTestCase = struct {
|
|||
Language: "java",
|
||||
Licenses: []string{},
|
||||
Type: "java-archive",
|
||||
CPEs: []pkg.CPE{
|
||||
must(pkg.NewCPE("cpe:2.3:a:charsets:charsets:*:*:*:*:*:java:*:*")),
|
||||
must(pkg.NewCPE("cpe:2.3:a:charsets:charsets:*:*:*:*:*:maven:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:a:charsets:charsets:*:*:*:*:*:java:*:*"),
|
||||
cpe.Must("cpe:2.3:a:charsets:charsets:*:*:*:*:*:maven:*:*"),
|
||||
},
|
||||
PURL: "",
|
||||
MetadataType: JavaMetadataType,
|
||||
|
@ -399,9 +392,9 @@ var springImageTestCase = struct {
|
|||
Language: "java",
|
||||
Licenses: []string{},
|
||||
Type: "java-archive",
|
||||
CPEs: []pkg.CPE{
|
||||
must(pkg.NewCPE("cpe:2.3:a:tomcat_embed_el:tomcat-embed-el:9.0.27:*:*:*:*:java:*:*")),
|
||||
must(pkg.NewCPE("cpe:2.3:a:tomcat-embed-el:tomcat_embed_el:9.0.27:*:*:*:*:maven:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:a:tomcat_embed_el:tomcat-embed-el:9.0.27:*:*:*:*:java:*:*"),
|
||||
cpe.Must("cpe:2.3:a:tomcat-embed-el:tomcat_embed_el:9.0.27:*:*:*:*:maven:*:*"),
|
||||
},
|
||||
PURL: "",
|
||||
MetadataType: JavaMetadataType,
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
|
||||
"github.com/scylladb/go-set/strset"
|
||||
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/cpe"
|
||||
)
|
||||
|
||||
type UpstreamPackage struct {
|
||||
|
@ -30,20 +30,20 @@ func UpstreamPackages(p Package) (pkgs []Package) {
|
|||
|
||||
// for each cpe, replace pkg name with origin and add to set
|
||||
cpeStrings := strset.New()
|
||||
for _, cpe := range tmp.CPEs {
|
||||
for _, c := range tmp.CPEs {
|
||||
if u.Version != "" {
|
||||
cpe.Version = u.Version
|
||||
c.Version = u.Version
|
||||
}
|
||||
|
||||
updatedCPEString := strings.ReplaceAll(cpe.BindToFmtString(), p.Name, u.Name)
|
||||
updatedCPEString := strings.ReplaceAll(c.BindToFmtString(), p.Name, u.Name)
|
||||
|
||||
cpeStrings.Add(updatedCPEString)
|
||||
}
|
||||
|
||||
// with each entry in set, convert string to CPE and update the new CPEs
|
||||
var updatedCPEs []pkg.CPE
|
||||
var updatedCPEs []cpe.CPE
|
||||
for _, cpeString := range cpeStrings.List() {
|
||||
updatedCPE, _ := pkg.NewCPE(cpeString)
|
||||
updatedCPE, _ := cpe.New(cpeString)
|
||||
updatedCPEs = append(updatedCPEs, updatedCPE)
|
||||
}
|
||||
tmp.CPEs = updatedCPEs
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/cpe"
|
||||
)
|
||||
|
||||
func TestUpstreamPackages(t *testing.T) {
|
||||
|
@ -27,8 +27,8 @@ func TestUpstreamPackages(t *testing.T) {
|
|||
pkg: Package{
|
||||
Name: "name",
|
||||
Version: "version",
|
||||
CPEs: []pkg.CPE{
|
||||
must(pkg.NewCPE("cpe:2.3:*:name:name:version:*:*:*:*:*:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:name:name:version:*:*:*:*:*:*:*"),
|
||||
},
|
||||
Upstreams: []UpstreamPackage{
|
||||
{
|
||||
|
@ -40,9 +40,9 @@ func TestUpstreamPackages(t *testing.T) {
|
|||
{
|
||||
Name: "new-name", // new
|
||||
Version: "version", // original
|
||||
CPEs: []pkg.CPE{
|
||||
CPEs: []cpe.CPE{
|
||||
// name and vendor replaced
|
||||
must(pkg.NewCPE("cpe:2.3:*:new-name:new-name:version:*:*:*:*:*:*:*")),
|
||||
cpe.Must("cpe:2.3:*:new-name:new-name:version:*:*:*:*:*:*:*"),
|
||||
},
|
||||
// no upstreams
|
||||
},
|
||||
|
@ -53,8 +53,8 @@ func TestUpstreamPackages(t *testing.T) {
|
|||
pkg: Package{
|
||||
Name: "name",
|
||||
Version: "version",
|
||||
CPEs: []pkg.CPE{
|
||||
must(pkg.NewCPE("cpe:2.3:*:name:name:version:*:*:*:*:*:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:name:name:version:*:*:*:*:*:*:*"),
|
||||
},
|
||||
Upstreams: []UpstreamPackage{
|
||||
{
|
||||
|
@ -67,9 +67,9 @@ func TestUpstreamPackages(t *testing.T) {
|
|||
{
|
||||
Name: "new-name", // new
|
||||
Version: "new-version", // new
|
||||
CPEs: []pkg.CPE{
|
||||
CPEs: []cpe.CPE{
|
||||
// name, vendor, and version replaced
|
||||
must(pkg.NewCPE("cpe:2.3:*:new-name:new-name:new-version:*:*:*:*:*:*:*")),
|
||||
cpe.Must("cpe:2.3:*:new-name:new-name:new-version:*:*:*:*:*:*:*"),
|
||||
},
|
||||
// no upstreams
|
||||
},
|
||||
|
@ -80,8 +80,8 @@ func TestUpstreamPackages(t *testing.T) {
|
|||
pkg: Package{
|
||||
Name: "name",
|
||||
Version: "version",
|
||||
CPEs: []pkg.CPE{
|
||||
must(pkg.NewCPE("cpe:2.3:*:name:name:version:*:*:*:*:*:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:name:name:version:*:*:*:*:*:*:*"),
|
||||
},
|
||||
Upstreams: []UpstreamPackage{
|
||||
{
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/anchore/grype/grype/pkg"
|
||||
"github.com/anchore/grype/grype/vulnerability"
|
||||
"github.com/anchore/stereoscope/pkg/image"
|
||||
"github.com/anchore/syft/syft/cpe"
|
||||
"github.com/anchore/syft/syft/linux"
|
||||
syftPkg "github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
|
@ -58,11 +59,11 @@ func Redact(s []byte) []byte {
|
|||
serialPattern := regexp.MustCompile(`serialNumber="[a-zA-Z0-9\-:]+"`)
|
||||
uuidPattern := regexp.MustCompile(`urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}`)
|
||||
refPattern := regexp.MustCompile(`ref="[a-zA-Z0-9\-:]+"`)
|
||||
rfc3339Pattern := regexp.MustCompile(`([0-9]+)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])[Tt]([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\.[0-9]+)?(([Zz])|([\+|\-]([01][0-9]|2[0-3]):[0-5][0-9]))`)
|
||||
rfc3339Pattern := regexp.MustCompile(`([0-9]+)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])[Tt]([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\.[0-9]+)?(([Zz])|([+|\-]([01][0-9]|2[0-3]):[0-5][0-9]))`)
|
||||
cycloneDxBomRefPattern := regexp.MustCompile(`[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}`)
|
||||
|
||||
for _, pattern := range []*regexp.Regexp{serialPattern, rfc3339Pattern, refPattern, uuidPattern, cycloneDxBomRefPattern} {
|
||||
s = pattern.ReplaceAll(s, []byte("redacted"))
|
||||
s = pattern.ReplaceAll(s, []byte(""))
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
@ -135,7 +136,7 @@ func generatePackages(t *testing.T) []pkg.Package {
|
|||
Version: "1.1.1",
|
||||
Type: syftPkg.RpmPkg,
|
||||
Locations: syftSource.NewLocationSet(syftSource.NewVirtualLocation("/foo/bar/somefile-1.txt", "somefile-1.txt")),
|
||||
CPEs: []syftPkg.CPE{
|
||||
CPEs: []cpe.CPE{
|
||||
{
|
||||
Part: "a",
|
||||
Vendor: "anchore",
|
||||
|
@ -161,7 +162,7 @@ func generatePackages(t *testing.T) []pkg.Package {
|
|||
Version: "2.2.2",
|
||||
Type: syftPkg.DebPkg,
|
||||
Locations: syftSource.NewLocationSet(syftSource.NewVirtualLocation("/foo/bar/somefile-2.txt", "somefile-2.txt")),
|
||||
CPEs: []syftPkg.CPE{
|
||||
CPEs: []cpe.CPE{
|
||||
{
|
||||
Part: "a",
|
||||
Vendor: "anchore",
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
"github.com/anchore/grype/grype/pkg"
|
||||
"github.com/anchore/grype/grype/version"
|
||||
"github.com/anchore/grype/grype/vulnerability"
|
||||
syftPkg "github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/cpe"
|
||||
)
|
||||
|
||||
type CPEParameters struct {
|
||||
|
@ -61,9 +61,9 @@ func ByPackageCPE(store vulnerability.ProviderByCPE, p pkg.Package, upstreamMatc
|
|||
// we attempt to merge match details within the same matcher when searching by CPEs, in this way there are fewer duplicated match
|
||||
// objects (and fewer duplicated match details).
|
||||
matchesByFingerprint := make(map[match.Fingerprint]match.Match)
|
||||
for _, cpe := range p.CPEs {
|
||||
for _, c := range p.CPEs {
|
||||
// prefer the CPE version, but if npt specified use the package version
|
||||
searchVersion := cpe.Version
|
||||
searchVersion := c.Version
|
||||
if searchVersion == wfn.NA || searchVersion == wfn.Any {
|
||||
searchVersion = p.Version
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ func ByPackageCPE(store vulnerability.ProviderByCPE, p pkg.Package, upstreamMatc
|
|||
}
|
||||
|
||||
// find all vulnerability records in the DB for the given CPE (not including version comparisons)
|
||||
allPkgVulns, err := store.GetByCPE(cpe)
|
||||
allPkgVulns, err := store.GetByCPE(c)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("matcher failed to fetch by CPE pkg=%q: %w", p.Name, err)
|
||||
}
|
||||
|
@ -95,14 +95,14 @@ func ByPackageCPE(store vulnerability.ProviderByCPE, p pkg.Package, upstreamMatc
|
|||
// relative to the current version information from the CPE (or the package) then the given package
|
||||
// is vulnerable.
|
||||
for _, vuln := range applicableVulns {
|
||||
addNewMatch(matchesByFingerprint, vuln, p, *verObj, upstreamMatcher, cpe)
|
||||
addNewMatch(matchesByFingerprint, vuln, p, *verObj, upstreamMatcher, c)
|
||||
}
|
||||
}
|
||||
|
||||
return toMatches(matchesByFingerprint), nil
|
||||
}
|
||||
|
||||
func addNewMatch(matchesByFingerprint map[match.Fingerprint]match.Match, vuln vulnerability.Vulnerability, p pkg.Package, searchVersion version.Version, upstreamMatcher match.MatcherType, searchedByCPE syftPkg.CPE) {
|
||||
func addNewMatch(matchesByFingerprint map[match.Fingerprint]match.Match, vuln vulnerability.Vulnerability, p pkg.Package, searchVersion version.Version, upstreamMatcher match.MatcherType, searchedByCPE cpe.CPE) {
|
||||
candidateMatch := match.Match{
|
||||
|
||||
Vulnerability: vuln,
|
||||
|
@ -174,7 +174,7 @@ func addMatchDetails(existingDetails []match.Detail, newDetails match.Detail) []
|
|||
return existingDetails
|
||||
}
|
||||
|
||||
func filterCPEsByVersion(pkgVersion version.Version, allCPEs []syftPkg.CPE) (matchedCPEs []syftPkg.CPE) {
|
||||
func filterCPEsByVersion(pkgVersion version.Version, allCPEs []cpe.CPE) (matchedCPEs []cpe.CPE) {
|
||||
for _, c := range allCPEs {
|
||||
if c.Version == wfn.Any || c.Version == wfn.NA {
|
||||
matchedCPEs = append(matchedCPEs, c)
|
||||
|
@ -207,10 +207,10 @@ func toMatches(matchesByFingerprint map[match.Fingerprint]match.Match) (matches
|
|||
}
|
||||
|
||||
// cpesToString receives one or more CPEs and stringifies them
|
||||
func cpesToString(cpes []syftPkg.CPE) []string {
|
||||
func cpesToString(cpes []cpe.CPE) []string {
|
||||
var strs = make([]string, len(cpes))
|
||||
for idx, cpe := range cpes {
|
||||
strs[idx] = cpe.BindToFmtString()
|
||||
for idx, c := range cpes {
|
||||
strs[idx] = c.BindToFmtString()
|
||||
}
|
||||
sort.Strings(strs)
|
||||
return strs
|
||||
|
|
|
@ -14,16 +14,10 @@ import (
|
|||
"github.com/anchore/grype/grype/pkg"
|
||||
"github.com/anchore/grype/grype/version"
|
||||
"github.com/anchore/grype/grype/vulnerability"
|
||||
"github.com/anchore/syft/syft/cpe"
|
||||
syftPkg "github.com/anchore/syft/syft/pkg"
|
||||
)
|
||||
|
||||
func must(c syftPkg.CPE, e error) syftPkg.CPE {
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
var _ grypeDB.VulnerabilityStoreReader = (*mockVulnStore)(nil)
|
||||
|
||||
type mockVulnStore struct {
|
||||
|
@ -171,9 +165,9 @@ func TestFindMatchesByPackageCPE(t *testing.T) {
|
|||
{
|
||||
name: "match from range",
|
||||
p: pkg.Package{
|
||||
CPEs: []syftPkg.CPE{
|
||||
must(syftPkg.NewCPE("cpe:2.3:*:activerecord:activerecord:3.7.5:rando1:*:ra:*:ruby:*:*")),
|
||||
must(syftPkg.NewCPE("cpe:2.3:*:activerecord:activerecord:3.7.5:rando4:*:re:*:rails:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:activerecord:activerecord:3.7.5:rando1:*:ra:*:ruby:*:*"),
|
||||
cpe.Must("cpe:2.3:*:activerecord:activerecord:3.7.5:rando4:*:re:*:rails:*:*"),
|
||||
},
|
||||
Name: "activerecord",
|
||||
Version: "3.7.5",
|
||||
|
@ -187,9 +181,9 @@ func TestFindMatchesByPackageCPE(t *testing.T) {
|
|||
ID: "CVE-2017-fake-1",
|
||||
},
|
||||
Package: pkg.Package{
|
||||
CPEs: []syftPkg.CPE{
|
||||
must(syftPkg.NewCPE("cpe:2.3:*:activerecord:activerecord:3.7.5:rando1:*:ra:*:ruby:*:*")),
|
||||
must(syftPkg.NewCPE("cpe:2.3:*:activerecord:activerecord:3.7.5:rando4:*:re:*:rails:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:activerecord:activerecord:3.7.5:rando1:*:ra:*:ruby:*:*"),
|
||||
cpe.Must("cpe:2.3:*:activerecord:activerecord:3.7.5:rando4:*:re:*:rails:*:*"),
|
||||
},
|
||||
Name: "activerecord",
|
||||
Version: "3.7.5",
|
||||
|
@ -218,9 +212,9 @@ func TestFindMatchesByPackageCPE(t *testing.T) {
|
|||
{
|
||||
name: "multiple matches",
|
||||
p: pkg.Package{
|
||||
CPEs: []syftPkg.CPE{
|
||||
must(syftPkg.NewCPE("cpe:2.3:*:activerecord:activerecord:3.7.3:rando1:*:ra:*:ruby:*:*")),
|
||||
must(syftPkg.NewCPE("cpe:2.3:*:activerecord:activerecord:3.7.3:rando4:*:re:*:rails:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:activerecord:activerecord:3.7.3:rando1:*:ra:*:ruby:*:*"),
|
||||
cpe.Must("cpe:2.3:*:activerecord:activerecord:3.7.3:rando4:*:re:*:rails:*:*"),
|
||||
},
|
||||
Name: "activerecord",
|
||||
Version: "3.7.3",
|
||||
|
@ -234,9 +228,9 @@ func TestFindMatchesByPackageCPE(t *testing.T) {
|
|||
ID: "CVE-2017-fake-1",
|
||||
},
|
||||
Package: pkg.Package{
|
||||
CPEs: []syftPkg.CPE{
|
||||
must(syftPkg.NewCPE("cpe:2.3:*:activerecord:activerecord:3.7.3:rando1:*:ra:*:ruby:*:*")),
|
||||
must(syftPkg.NewCPE("cpe:2.3:*:activerecord:activerecord:3.7.3:rando4:*:re:*:rails:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:activerecord:activerecord:3.7.3:rando1:*:ra:*:ruby:*:*"),
|
||||
cpe.Must("cpe:2.3:*:activerecord:activerecord:3.7.3:rando4:*:re:*:rails:*:*"),
|
||||
},
|
||||
Name: "activerecord",
|
||||
Version: "3.7.3",
|
||||
|
@ -269,9 +263,9 @@ func TestFindMatchesByPackageCPE(t *testing.T) {
|
|||
ID: "CVE-2017-fake-2",
|
||||
},
|
||||
Package: pkg.Package{
|
||||
CPEs: []syftPkg.CPE{
|
||||
must(syftPkg.NewCPE("cpe:2.3:*:activerecord:activerecord:3.7.3:rando1:*:ra:*:ruby:*:*")),
|
||||
must(syftPkg.NewCPE("cpe:2.3:*:activerecord:activerecord:3.7.3:rando4:*:re:*:rails:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:activerecord:activerecord:3.7.3:rando1:*:ra:*:ruby:*:*"),
|
||||
cpe.Must("cpe:2.3:*:activerecord:activerecord:3.7.3:rando4:*:re:*:rails:*:*"),
|
||||
},
|
||||
Name: "activerecord",
|
||||
Version: "3.7.3",
|
||||
|
@ -301,8 +295,8 @@ func TestFindMatchesByPackageCPE(t *testing.T) {
|
|||
{
|
||||
name: "exact match",
|
||||
p: pkg.Package{
|
||||
CPEs: []syftPkg.CPE{
|
||||
must(syftPkg.NewCPE("cpe:2.3:*:*:activerecord:4.0.1:*:*:*:*:*:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:*:activerecord:4.0.1:*:*:*:*:*:*:*"),
|
||||
},
|
||||
Name: "activerecord",
|
||||
Version: "4.0.1",
|
||||
|
@ -316,8 +310,8 @@ func TestFindMatchesByPackageCPE(t *testing.T) {
|
|||
ID: "CVE-2017-fake-3",
|
||||
},
|
||||
Package: pkg.Package{
|
||||
CPEs: []syftPkg.CPE{
|
||||
must(syftPkg.NewCPE("cpe:2.3:*:*:activerecord:4.0.1:*:*:*:*:*:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:*:activerecord:4.0.1:*:*:*:*:*:*:*"),
|
||||
},
|
||||
Name: "activerecord",
|
||||
Version: "4.0.1",
|
||||
|
@ -357,8 +351,8 @@ func TestFindMatchesByPackageCPE(t *testing.T) {
|
|||
{
|
||||
name: "fuzzy version match",
|
||||
p: pkg.Package{
|
||||
CPEs: []syftPkg.CPE{
|
||||
must(syftPkg.NewCPE("cpe:2.3:*:awesome:awesome:98SE1:rando1:*:ra:*:dunno:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:awesome:awesome:98SE1:rando1:*:ra:*:dunno:*:*"),
|
||||
},
|
||||
Name: "awesome",
|
||||
Version: "98SE1",
|
||||
|
@ -370,8 +364,8 @@ func TestFindMatchesByPackageCPE(t *testing.T) {
|
|||
ID: "CVE-2017-fake-4",
|
||||
},
|
||||
Package: pkg.Package{
|
||||
CPEs: []syftPkg.CPE{
|
||||
must(syftPkg.NewCPE("cpe:2.3:*:awesome:awesome:98SE1:rando1:*:ra:*:dunno:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:awesome:awesome:98SE1:rando1:*:ra:*:dunno:*:*"),
|
||||
},
|
||||
Name: "awesome",
|
||||
Version: "98SE1",
|
||||
|
@ -399,8 +393,8 @@ func TestFindMatchesByPackageCPE(t *testing.T) {
|
|||
{
|
||||
name: "multiple matched CPEs",
|
||||
p: pkg.Package{
|
||||
CPEs: []syftPkg.CPE{
|
||||
must(syftPkg.NewCPE("cpe:2.3:*:multiple:multiple:1.0:*:*:*:*:*:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:multiple:multiple:1.0:*:*:*:*:*:*:*"),
|
||||
},
|
||||
Name: "multiple",
|
||||
Version: "1.0",
|
||||
|
@ -414,8 +408,8 @@ func TestFindMatchesByPackageCPE(t *testing.T) {
|
|||
ID: "CVE-2017-fake-5",
|
||||
},
|
||||
Package: pkg.Package{
|
||||
CPEs: []syftPkg.CPE{
|
||||
must(syftPkg.NewCPE("cpe:2.3:*:multiple:multiple:1.0:*:*:*:*:*:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:multiple:multiple:1.0:*:*:*:*:*:*:*"),
|
||||
},
|
||||
Name: "multiple",
|
||||
Version: "1.0",
|
||||
|
@ -448,8 +442,8 @@ func TestFindMatchesByPackageCPE(t *testing.T) {
|
|||
{
|
||||
name: "filtered out match due to target_sw mismatch",
|
||||
p: pkg.Package{
|
||||
CPEs: []syftPkg.CPE{
|
||||
must(syftPkg.NewCPE("cpe:2.3:*:funfun:funfun:*:*:*:*:*:*:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:funfun:funfun:*:*:*:*:*:*:*:*"),
|
||||
},
|
||||
Name: "funfun",
|
||||
Version: "5.2.1",
|
||||
|
@ -461,8 +455,8 @@ func TestFindMatchesByPackageCPE(t *testing.T) {
|
|||
{
|
||||
name: "target_sw mismatch with unsupported target_sw",
|
||||
p: pkg.Package{
|
||||
CPEs: []syftPkg.CPE{
|
||||
must(syftPkg.NewCPE("cpe:2.3:*:sw:sw:*:*:*:*:*:*:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:sw:sw:*:*:*:*:*:*:*:*"),
|
||||
},
|
||||
Name: "sw",
|
||||
Version: "0.1",
|
||||
|
@ -475,8 +469,8 @@ func TestFindMatchesByPackageCPE(t *testing.T) {
|
|||
ID: "CVE-2017-fake-7",
|
||||
},
|
||||
Package: pkg.Package{
|
||||
CPEs: []syftPkg.CPE{
|
||||
must(syftPkg.NewCPE("cpe:2.3:*:sw:sw:*:*:*:*:*:*:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:sw:sw:*:*:*:*:*:*:*:*"),
|
||||
},
|
||||
Name: "sw",
|
||||
Version: "0.1",
|
||||
|
@ -507,11 +501,11 @@ func TestFindMatchesByPackageCPE(t *testing.T) {
|
|||
{
|
||||
name: "match included even though multiple cpes are mismatch",
|
||||
p: pkg.Package{
|
||||
CPEs: []syftPkg.CPE{
|
||||
must(syftPkg.NewCPE("cpe:2.3:*:funfun:funfun:*:*:*:*:*:rust:*:*")),
|
||||
must(syftPkg.NewCPE("cpe:2.3:*:funfun:funfun:*:*:*:*:*:rails:*:*")),
|
||||
must(syftPkg.NewCPE("cpe:2.3:*:funfun:funfun:*:*:*:*:*:ruby:*:*")),
|
||||
must(syftPkg.NewCPE("cpe:2.3:*:funfun:funfun:*:*:*:*:*:python:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:funfun:funfun:*:*:*:*:*:rust:*:*"),
|
||||
cpe.Must("cpe:2.3:*:funfun:funfun:*:*:*:*:*:rails:*:*"),
|
||||
cpe.Must("cpe:2.3:*:funfun:funfun:*:*:*:*:*:ruby:*:*"),
|
||||
cpe.Must("cpe:2.3:*:funfun:funfun:*:*:*:*:*:python:*:*"),
|
||||
},
|
||||
Name: "funfun",
|
||||
Version: "5.2.1",
|
||||
|
@ -524,11 +518,11 @@ func TestFindMatchesByPackageCPE(t *testing.T) {
|
|||
ID: "CVE-2017-fake-6",
|
||||
},
|
||||
Package: pkg.Package{
|
||||
CPEs: []syftPkg.CPE{
|
||||
must(syftPkg.NewCPE("cpe:2.3:*:funfun:funfun:*:*:*:*:*:rust:*:*")),
|
||||
must(syftPkg.NewCPE("cpe:2.3:*:funfun:funfun:*:*:*:*:*:rails:*:*")),
|
||||
must(syftPkg.NewCPE("cpe:2.3:*:funfun:funfun:*:*:*:*:*:ruby:*:*")),
|
||||
must(syftPkg.NewCPE("cpe:2.3:*:funfun:funfun:*:*:*:*:*:python:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:*:funfun:funfun:*:*:*:*:*:rust:*:*"),
|
||||
cpe.Must("cpe:2.3:*:funfun:funfun:*:*:*:*:*:rails:*:*"),
|
||||
cpe.Must("cpe:2.3:*:funfun:funfun:*:*:*:*:*:ruby:*:*"),
|
||||
cpe.Must("cpe:2.3:*:funfun:funfun:*:*:*:*:*:python:*:*"),
|
||||
},
|
||||
Name: "funfun",
|
||||
Version: "5.2.1",
|
||||
|
@ -560,8 +554,8 @@ func TestFindMatchesByPackageCPE(t *testing.T) {
|
|||
{
|
||||
name: "Ensure target_sw mismatch does not apply to java packages",
|
||||
p: pkg.Package{
|
||||
CPEs: []syftPkg.CPE{
|
||||
must(syftPkg.NewCPE("cpe:2.3:a:handlebarsjs:handlebars:*:*:*:*:*:*:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:a:handlebarsjs:handlebars:*:*:*:*:*:*:*:*"),
|
||||
},
|
||||
Name: "handlebars",
|
||||
Version: "0.1",
|
||||
|
@ -574,8 +568,8 @@ func TestFindMatchesByPackageCPE(t *testing.T) {
|
|||
ID: "CVE-2021-23369",
|
||||
},
|
||||
Package: pkg.Package{
|
||||
CPEs: []syftPkg.CPE{
|
||||
must(syftPkg.NewCPE("cpe:2.3:a:handlebarsjs:handlebars:*:*:*:*:*:*:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:a:handlebarsjs:handlebars:*:*:*:*:*:*:*:*"),
|
||||
},
|
||||
Name: "handlebars",
|
||||
Version: "0.1",
|
||||
|
@ -606,8 +600,8 @@ func TestFindMatchesByPackageCPE(t *testing.T) {
|
|||
{
|
||||
name: "Ensure target_sw mismatch does not apply to java jenkins plugins packages",
|
||||
p: pkg.Package{
|
||||
CPEs: []syftPkg.CPE{
|
||||
must(syftPkg.NewCPE("cpe:2.3:a:handlebarsjs:handlebars:*:*:*:*:*:*:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:a:handlebarsjs:handlebars:*:*:*:*:*:*:*:*"),
|
||||
},
|
||||
Name: "handlebars",
|
||||
Version: "0.1",
|
||||
|
@ -620,8 +614,8 @@ func TestFindMatchesByPackageCPE(t *testing.T) {
|
|||
ID: "CVE-2021-23369",
|
||||
},
|
||||
Package: pkg.Package{
|
||||
CPEs: []syftPkg.CPE{
|
||||
must(syftPkg.NewCPE("cpe:2.3:a:handlebarsjs:handlebars:*:*:*:*:*:*:*:*")),
|
||||
CPEs: []cpe.CPE{
|
||||
cpe.Must("cpe:2.3:a:handlebarsjs:handlebars:*:*:*:*:*:*:*:*"),
|
||||
},
|
||||
Name: "handlebars",
|
||||
Version: "0.1",
|
||||
|
@ -692,9 +686,9 @@ func TestFilterCPEsByVersion(t *testing.T) {
|
|||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
// format strings to CPE objects...
|
||||
vulnerabilityCPEs := make([]syftPkg.CPE, len(test.vulnerabilityCPEs))
|
||||
vulnerabilityCPEs := make([]cpe.CPE, len(test.vulnerabilityCPEs))
|
||||
for idx, c := range test.vulnerabilityCPEs {
|
||||
vulnerabilityCPEs[idx] = must(syftPkg.NewCPE(c))
|
||||
vulnerabilityCPEs[idx] = cpe.Must(c)
|
||||
}
|
||||
|
||||
versionObj, err := version.NewVersion(test.version, version.UnknownFormat)
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/anchore/grype/grype/pkg"
|
||||
syftPkg "github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/cpe"
|
||||
)
|
||||
|
||||
type Version struct {
|
||||
|
@ -14,7 +14,7 @@ type Version struct {
|
|||
}
|
||||
|
||||
type rich struct {
|
||||
cpeVers []syftPkg.CPE
|
||||
cpeVers []cpe.CPE
|
||||
semVer *semanticVersion
|
||||
apkVer *apkVersion
|
||||
debVer *debVersion
|
||||
|
@ -88,7 +88,7 @@ func (v *Version) populate() error {
|
|||
return fmt.Errorf("no rich version populated (format=%s)", v.Format)
|
||||
}
|
||||
|
||||
func (v Version) CPEs() []syftPkg.CPE {
|
||||
func (v Version) CPEs() []cpe.CPE {
|
||||
return v.rich.cpeVers
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package vulnerability
|
|||
import (
|
||||
"github.com/anchore/grype/grype/distro"
|
||||
"github.com/anchore/grype/grype/pkg"
|
||||
"github.com/anchore/syft/syft/cpe"
|
||||
syftPkg "github.com/anchore/syft/syft/pkg"
|
||||
)
|
||||
|
||||
|
@ -22,7 +23,7 @@ type ProviderByLanguage interface {
|
|||
}
|
||||
|
||||
type ProviderByCPE interface {
|
||||
GetByCPE(syftPkg.CPE) ([]Vulnerability, error)
|
||||
GetByCPE(cpe.CPE) ([]Vulnerability, error)
|
||||
}
|
||||
|
||||
type MetadataProvider interface {
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
grypeDB "github.com/anchore/grype/grype/db/v5"
|
||||
"github.com/anchore/grype/grype/pkg/qualifier"
|
||||
"github.com/anchore/grype/grype/version"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/cpe"
|
||||
)
|
||||
|
||||
type Reference struct {
|
||||
|
@ -17,7 +17,7 @@ type Reference struct {
|
|||
type Vulnerability struct {
|
||||
Constraint version.Constraint
|
||||
PackageQualifiers []qualifier.Qualifier
|
||||
CPEs []pkg.CPE
|
||||
CPEs []cpe.CPE
|
||||
ID string
|
||||
Namespace string
|
||||
Fix Fix
|
||||
|
@ -57,7 +57,7 @@ func NewVulnerability(vuln grypeDB.Vulnerability) (*Vulnerability, error) {
|
|||
return &Vulnerability{
|
||||
Constraint: constraint,
|
||||
ID: vuln.ID,
|
||||
CPEs: make([]pkg.CPE, 0),
|
||||
CPEs: make([]cpe.CPE, 0),
|
||||
Namespace: vuln.Namespace,
|
||||
PackageQualifiers: pkgQualifiers,
|
||||
Fix: Fix{
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
"github.com/anchore/grype/grype/store"
|
||||
"github.com/anchore/grype/grype/version"
|
||||
"github.com/anchore/grype/grype/vulnerability"
|
||||
"github.com/anchore/syft/syft/cpe"
|
||||
"github.com/anchore/syft/syft/linux"
|
||||
syftPkg "github.com/anchore/syft/syft/pkg"
|
||||
)
|
||||
|
@ -277,8 +278,8 @@ func TestVulnerabilityMatcher_FindMatches(t *testing.T) {
|
|||
Type: syftPkg.DebPkg,
|
||||
}
|
||||
|
||||
mustCPE := func(c string) syftPkg.CPE {
|
||||
cp, err := syftPkg.NewCPE(c)
|
||||
mustCPE := func(c string) cpe.CPE {
|
||||
cp, err := cpe.New(c)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -289,7 +290,7 @@ func TestVulnerabilityMatcher_FindMatches(t *testing.T) {
|
|||
ID: pkg.ID(uuid.NewString()),
|
||||
Name: "activerecord",
|
||||
Version: "3.7.5",
|
||||
CPEs: []syftPkg.CPE{
|
||||
CPEs: []cpe.CPE{
|
||||
mustCPE("cpe:2.3:*:activerecord:activerecord:*:*:*:*:*:rails:*:*"),
|
||||
},
|
||||
Type: syftPkg.GemPkg,
|
||||
|
@ -363,7 +364,7 @@ func TestVulnerabilityMatcher_FindMatches(t *testing.T) {
|
|||
ID: "CVE-2014-fake-1",
|
||||
Namespace: "debian:distro:debian:8",
|
||||
PackageQualifiers: []qualifier.Qualifier{},
|
||||
CPEs: []syftPkg.CPE{},
|
||||
CPEs: []cpe.CPE{},
|
||||
Advisories: []vulnerability.Advisory{},
|
||||
},
|
||||
Package: neutron2013Pkg,
|
||||
|
@ -416,7 +417,7 @@ func TestVulnerabilityMatcher_FindMatches(t *testing.T) {
|
|||
ID: "CVE-2014-fake-1",
|
||||
Namespace: "debian:distro:debian:8",
|
||||
PackageQualifiers: []qualifier.Qualifier{},
|
||||
CPEs: []syftPkg.CPE{},
|
||||
CPEs: []cpe.CPE{},
|
||||
Advisories: []vulnerability.Advisory{},
|
||||
},
|
||||
Package: neutron2013Pkg,
|
||||
|
@ -463,7 +464,7 @@ func TestVulnerabilityMatcher_FindMatches(t *testing.T) {
|
|||
Constraint: version.MustGetConstraint("< 3.7.6", version.UnknownFormat),
|
||||
ID: "CVE-2014-fake-3",
|
||||
Namespace: "nvd:cpe",
|
||||
CPEs: []syftPkg.CPE{
|
||||
CPEs: []cpe.CPE{
|
||||
mustCPE("cpe:2.3:*:activerecord:activerecord:*:*:*:*:*:rails:*:*"),
|
||||
},
|
||||
PackageQualifiers: []qualifier.Qualifier{},
|
||||
|
@ -504,7 +505,7 @@ func TestVulnerabilityMatcher_FindMatches(t *testing.T) {
|
|||
},
|
||||
PackageQualifiers: []qualifier.Qualifier{},
|
||||
Advisories: []vulnerability.Advisory{},
|
||||
CPEs: []syftPkg.CPE{},
|
||||
CPEs: []cpe.CPE{},
|
||||
},
|
||||
Package: activerecordPkg,
|
||||
Details: match.Details{
|
||||
|
@ -552,11 +553,17 @@ func TestVulnerabilityMatcher_FindMatches(t *testing.T) {
|
|||
Constraint: version.MustGetConstraint("< 3.7.6", version.UnknownFormat),
|
||||
ID: "CVE-2014-fake-3",
|
||||
Namespace: "nvd:cpe",
|
||||
CPEs: []syftPkg.CPE{
|
||||
CPEs: []cpe.CPE{
|
||||
mustCPE("cpe:2.3:*:activerecord:activerecord:*:*:*:*:*:rails:*:*"),
|
||||
},
|
||||
PackageQualifiers: []qualifier.Qualifier{},
|
||||
Advisories: []vulnerability.Advisory{},
|
||||
RelatedVulnerabilities: []vulnerability.Reference{
|
||||
{
|
||||
ID: "GHSA-2014-fake-3",
|
||||
Namespace: "github:language:ruby",
|
||||
},
|
||||
},
|
||||
},
|
||||
Package: activerecordPkg,
|
||||
Details: match.Details{
|
||||
|
@ -627,7 +634,7 @@ func TestVulnerabilityMatcher_FindMatches(t *testing.T) {
|
|||
Constraint: version.MustGetConstraint("< 3.7.6", version.UnknownFormat),
|
||||
ID: "CVE-2014-fake-3",
|
||||
Namespace: "nvd:cpe",
|
||||
CPEs: []syftPkg.CPE{
|
||||
CPEs: []cpe.CPE{
|
||||
mustCPE("cpe:2.3:*:activerecord:activerecord:*:*:*:*:*:rails:*:*"),
|
||||
},
|
||||
PackageQualifiers: []qualifier.Qualifier{},
|
||||
|
@ -695,7 +702,7 @@ func TestVulnerabilityMatcher_FindMatches(t *testing.T) {
|
|||
Constraint: version.MustGetConstraint("< 3.7.6", version.UnknownFormat),
|
||||
ID: "CVE-2014-fake-3",
|
||||
Namespace: "nvd:cpe",
|
||||
CPEs: []syftPkg.CPE{},
|
||||
CPEs: []cpe.CPE{},
|
||||
PackageQualifiers: []qualifier.Qualifier{},
|
||||
Advisories: []vulnerability.Advisory{},
|
||||
RelatedVulnerabilities: []vulnerability.Reference{
|
||||
|
@ -760,7 +767,7 @@ func TestVulnerabilityMatcher_FindMatches(t *testing.T) {
|
|||
},
|
||||
PackageQualifiers: []qualifier.Qualifier{},
|
||||
Advisories: []vulnerability.Advisory{},
|
||||
CPEs: []syftPkg.CPE{},
|
||||
CPEs: []cpe.CPE{},
|
||||
},
|
||||
Package: activerecordPkg,
|
||||
Details: match.Details{
|
||||
|
@ -792,7 +799,7 @@ func TestVulnerabilityMatcher_FindMatches(t *testing.T) {
|
|||
Constraint: version.MustGetConstraint("< 3.7.6", version.UnknownFormat),
|
||||
ID: "CVE-2014-fake-3",
|
||||
Namespace: "nvd:cpe",
|
||||
CPEs: []syftPkg.CPE{
|
||||
CPEs: []cpe.CPE{
|
||||
mustCPE("cpe:2.3:*:activerecord:activerecord:*:*:*:*:*:rails:*:*"),
|
||||
},
|
||||
PackageQualifiers: []qualifier.Qualifier{},
|
||||
|
|
|
@ -41,26 +41,6 @@ func addAlpineMatches(t *testing.T, theSource source.Source, catalog *syftPkg.Ca
|
|||
Vulnerability: *vulnObj,
|
||||
Package: thePkg,
|
||||
Details: []match.Detail{
|
||||
{
|
||||
Type: match.ExactDirectMatch,
|
||||
Confidence: 1.0,
|
||||
SearchedBy: map[string]interface{}{
|
||||
"distro": map[string]string{
|
||||
"type": "alpine",
|
||||
"version": "3.12.0",
|
||||
},
|
||||
"namespace": "alpine:distro:alpine:3.12",
|
||||
"package": map[string]string{
|
||||
"name": "libvncserver",
|
||||
"version": "0.9.9",
|
||||
},
|
||||
},
|
||||
Found: map[string]interface{}{
|
||||
"versionConstraint": "< 0.9.10 (unknown)",
|
||||
"vulnerabilityID": vulnObj.ID,
|
||||
},
|
||||
Matcher: match.ApkMatcher,
|
||||
},
|
||||
{
|
||||
// note: the input pURL has an upstream reference (redundant)
|
||||
Type: "exact-indirect-match",
|
||||
|
@ -82,6 +62,26 @@ func addAlpineMatches(t *testing.T, theSource source.Source, catalog *syftPkg.Ca
|
|||
Matcher: "apk-matcher",
|
||||
Confidence: 1,
|
||||
},
|
||||
{
|
||||
Type: match.ExactDirectMatch,
|
||||
Confidence: 1.0,
|
||||
SearchedBy: map[string]interface{}{
|
||||
"distro": map[string]string{
|
||||
"type": "alpine",
|
||||
"version": "3.12.0",
|
||||
},
|
||||
"namespace": "alpine:distro:alpine:3.12",
|
||||
"package": map[string]string{
|
||||
"name": "libvncserver",
|
||||
"version": "0.9.9",
|
||||
},
|
||||
},
|
||||
Found: map[string]interface{}{
|
||||
"versionConstraint": "< 0.9.10 (unknown)",
|
||||
"vulnerabilityID": vulnObj.ID,
|
||||
},
|
||||
Matcher: match.ApkMatcher,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 6120c083b3ea0544c2b8210018b992aaac337997
|
||||
Subproject commit 0127621fd2bd23a3b2a7e610b97c05bc9d6c0c4f
|
Loading…
Reference in a new issue