fix: orient by cve merging (#1046)

This commit is contained in:
Keith Zantow 2023-01-04 13:41:10 -05:00 committed by GitHub
parent 3ff1d64eab
commit 04a84a4440
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 319 additions and 294 deletions

2
go.mod
View file

@ -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
View file

@ -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=

View file

@ -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) {

View file

@ -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:*:*:*:*:*:*:*"),
},
},
}

View file

@ -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)

View file

@ -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{},
},
}

View file

@ -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)
}

View file

@ -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{
{

View file

@ -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
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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

View file

@ -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{
{},
},
})

View file

@ -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)
}
}
}

View file

@ -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,

View file

@ -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

View file

@ -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{
{

View file

@ -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",

View file

@ -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

View file

@ -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)

View file

@ -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
}

View file

@ -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 {

View file

@ -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{

View file

@ -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{},

View file

@ -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