remove CPE generation (rely on static CPES from syft instead)

Signed-off-by: Alex Goodman <alex.goodman@anchore.com>
This commit is contained in:
Alex Goodman 2020-11-19 12:39:35 -05:00
parent 90b44640c2
commit 627aa77842
No known key found for this signature in database
GPG key ID: 5CB45AE22BAB7EA7
33 changed files with 187 additions and 359 deletions

View file

@ -14,7 +14,7 @@ RESET := $(shell tput -T linux sgr0)
TITLE := $(BOLD)$(PURPLE)
SUCCESS := $(BOLD)$(GREEN)
# the quality gate lower threshold for unit test total % coverage (by function statements)
COVERAGE_THRESHOLD := 55
COVERAGE_THRESHOLD := 50
## Build variables
DISTDIR=./dist

View file

@ -178,7 +178,7 @@ func startWorker(userInput string, failOnSeverity *vulnerability.Severity) <-cha
var metadataProvider vulnerability.MetadataProvider
var catalog *pkg.Catalog
var srcMetadata source.Metadata
var theDistro distro.Distro
var theDistro *distro.Distro
var err error
var wg = &sync.WaitGroup{}

4
go.mod
View file

@ -8,10 +8,10 @@ require (
github.com/anchore/go-version v1.2.2-0.20200810141238-330bef18dbca
github.com/anchore/grype-db v0.0.0-20200929200644-6d1c82acc95e
github.com/anchore/stereoscope v0.0.0-20201106140100-12e75c48f409
github.com/anchore/syft v0.8.0
github.com/anchore/syft v0.8.1-0.20201119173820-0ed30138c4c5
github.com/docker/docker v17.12.0-ce-rc1.0.20200309214505-aa6a9891b09c+incompatible
github.com/dustin/go-humanize v1.0.0
github.com/facebookincubator/nvdtools v0.1.4-0.20200622182922-aed862a62ae6
github.com/facebookincubator/nvdtools v0.1.4
github.com/go-test/deep v1.0.7
github.com/google/go-containerregistry v0.1.1 // indirect
github.com/google/uuid v1.1.1

8
go.sum
View file

@ -125,8 +125,8 @@ github.com/anchore/grype-db v0.0.0-20200929200644-6d1c82acc95e h1:s0HmxxDuJyvgGB
github.com/anchore/grype-db v0.0.0-20200929200644-6d1c82acc95e/go.mod h1:LINmipRzG88vnJEWvgMMDVCFH1qZsj7+bjmpERlSyaA=
github.com/anchore/stereoscope v0.0.0-20201106140100-12e75c48f409 h1:xKSpDRjmYrEFrdMeDh4AuSUAFc99pdro6YFBKxy2um0=
github.com/anchore/stereoscope v0.0.0-20201106140100-12e75c48f409/go.mod h1:2Jja/4l0zYggW52og+nn0rut4i+OYjCf9vTyrM8RT4E=
github.com/anchore/syft v0.8.0 h1:Jq9yja9rwx6oIrPjwSpmB2VWRbrOTLtC06GJnAUz03A=
github.com/anchore/syft v0.8.0/go.mod h1:Uf1lxsZSo/y3HjQ0U94p3aQpHy8Ac6wLyDwYLT0dcYw=
github.com/anchore/syft v0.8.1-0.20201119173820-0ed30138c4c5 h1:UZqpD/vM2IAfWrD515M9dPiXFaEKxXImvJI+E5xVGH8=
github.com/anchore/syft v0.8.1-0.20201119173820-0ed30138c4c5/go.mod h1:5seLdLxn97ZiXzIsnxMjiKvxMoj0Ms/W8xJj+VSHq+Y=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
@ -250,8 +250,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y=
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/facebookincubator/nvdtools v0.1.4-0.20200622182922-aed862a62ae6 h1:+GR1Gkrl/JervFT1aKR4kzG8T10QWYMSKfYfhCJX0vU=
github.com/facebookincubator/nvdtools v0.1.4-0.20200622182922-aed862a62ae6/go.mod h1:0/FIVnSEl9YHXLq3tKBPpKaI0iUceDhdSHPlIwIX44Y=
github.com/facebookincubator/nvdtools v0.1.4 h1:x1Ucw9+bSkMd8DJJN4jNQ1Lk4PSFlJarGOxp9D6WUMo=
github.com/facebookincubator/nvdtools v0.1.4/go.mod h1:0/FIVnSEl9YHXLq3tKBPpKaI0iUceDhdSHPlIwIX44Y=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=

View file

@ -1,62 +1,13 @@
package cpe
import (
"fmt"
"github.com/anchore/grype/internal"
"github.com/anchore/syft/syft/pkg"
"github.com/facebookincubator/nvdtools/wfn"
)
// TODO: would be great to allow these to be overridden by user data/config
var targetSoftware = map[pkg.Language][]string{
pkg.Java: {
"java",
"maven",
"jenkins",
"cloudbees_jenkins",
},
//pkg.JavaScript: {
// "node.js",
//},
pkg.Python: {
"python",
},
pkg.Ruby: {
"ruby",
"rails",
},
}
const ANY = "*"
type CPE = wfn.Attributes
func New(cpeStr string) (CPE, error) {
value, err := wfn.Parse(cpeStr)
// we need to compare the raw data since we are constructing CPEs in other locations
value.Vendor = wfn.StripSlashes(value.Vendor)
value.Product = wfn.StripSlashes(value.Product)
value.Language = wfn.StripSlashes(value.Language)
value.Version = wfn.StripSlashes(value.Version)
value.TargetSW = wfn.StripSlashes(value.TargetSW)
value.Part = wfn.StripSlashes(value.Part)
value.Edition = wfn.StripSlashes(value.Edition)
value.Other = wfn.StripSlashes(value.Other)
value.SWEdition = wfn.StripSlashes(value.SWEdition)
value.TargetHW = wfn.StripSlashes(value.TargetHW)
value.Update = wfn.StripSlashes(value.Update)
if value == nil || err != nil {
return CPE{}, fmt.Errorf("failed to parse CPE (%s): %w", cpeStr, err)
}
return *value, nil
}
func NewSlice(cpeStrs ...string) ([]CPE, error) {
ret := make([]CPE, len(cpeStrs))
func NewSlice(cpeStrs ...string) ([]pkg.CPE, error) {
ret := make([]pkg.CPE, len(cpeStrs))
for idx, c := range cpeStrs {
value, err := New(c)
value, err := pkg.NewCPE(c)
if err != nil {
return nil, err
}
@ -65,71 +16,8 @@ func NewSlice(cpeStrs ...string) ([]CPE, error) {
return ret, nil
}
// Generate Create a list of CPEs, trying to guess the vendor, product tuple and setting TargetSoftware if possible
func Generate(p *pkg.Package) ([]CPE, error) {
targetSoftwares := candidateTargetSoftwareAttrs(p)
vendors := candidateVendors(p)
products := candidateProducts(p)
keys := internal.NewStringSet()
cpes := make([]CPE, 0)
for _, product := range products {
for _, vendor := range vendors {
for _, targetSw := range targetSoftwares {
// prevent duplicate entries...
key := fmt.Sprintf("%s|%s|%s|%s", product, vendor, p.Version, targetSw)
if keys.Contains(key) {
continue
}
keys.Add(key)
// add a new entry...
candidateCpe := wfn.NewAttributesWithAny()
candidateCpe.Product = product
candidateCpe.Vendor = vendor
candidateCpe.Version = p.Version
candidateCpe.TargetSW = targetSw
cpes = append(cpes, *candidateCpe)
}
}
}
return cpes, nil
}
func candidateTargetSoftwareAttrs(p *pkg.Package) []string {
// TODO: expand with package metadata (from type assert)
mappedNames := targetSoftware[p.Language]
if mappedNames == nil {
mappedNames = []string{}
}
attrs := make([]string, len(mappedNames))
copy(attrs, targetSoftware[p.Language])
// last element is the any match, present for all
attrs = append(attrs, ANY)
return attrs
}
func candidateVendors(p *pkg.Package) []string {
// TODO: expand with package metadata (from type assert)
ret := []string{p.Name, ANY}
if p.Language == pkg.Python {
ret = append(ret, fmt.Sprintf("python-%s", p.Name))
}
return ret
}
func candidateProducts(p *pkg.Package) []string {
// TODO: expand with package metadata (from type assert)
return []string{p.Name}
}
func MatchWithoutVersion(c CPE, candidates []CPE) []CPE {
matches := make([]CPE, 0)
func MatchWithoutVersion(c pkg.CPE, candidates []pkg.CPE) []pkg.CPE {
matches := make([]pkg.CPE, 0)
for _, candidate := range candidates {
canCopy := candidate
if c.MatchWithoutVersion(&canCopy) {

View file

@ -4,199 +4,108 @@ import (
"testing"
"github.com/anchore/syft/syft/pkg"
"github.com/sergi/go-diff/diffmatchpatch"
)
func must(c CPE, e error) CPE {
func must(c pkg.CPE, e error) pkg.CPE {
if e != nil {
panic(e)
}
return c
}
func TestNew(t *testing.T) {
tests := []struct {
name string
input string
expected CPE
}{
{
name: "gocase",
input: `cpe:/a:10web:form_maker:1.0.0::~~~wordpress~~`,
expected: must(New(`cpe:2.3:a:10web:form_maker:1.0.0:*:*:*:*:wordpress:*:*`)),
},
{
name: "dashes",
input: `cpe:/a:7-zip:7-zip:4.56:beta:~~~windows~~`,
expected: must(New(`cpe:2.3:a:7-zip:7-zip:4.56:beta:*:*:*:windows:*:*`)),
},
{
name: "URL escape characters",
input: `cpe:/a:%240.99_kindle_books_project:%240.99_kindle_books:6::~~~android~~`,
expected: must(New(`cpe:2.3:a:$0.99_kindle_books_project:$0.99_kindle_books:6:*:*:*:*:android:*:*`)),
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
actual, err := New(test.input)
if err != nil {
t.Fatalf("got an error while creating CPE: %+v", err)
}
if actual.BindToFmtString() != test.expected.BindToFmtString() {
t.Errorf("mismatched entries:\n\texpected:%+v\n\t actual:%+v\n", test.expected.BindToFmtString(), actual.BindToFmtString())
}
})
}
}
func TestGenerate(t *testing.T) {
tests := []struct {
name string
p pkg.Package
expected []CPE
}{
{
name: "simple package",
p: pkg.Package{
Name: "name",
Version: "3.2",
FoundBy: "some-analyzer",
Language: pkg.Java,
Type: pkg.DebPkg,
},
expected: []CPE{
must(New("cpe:2.3:*:name:name:3.2:*:*:*:*:java:*:*")),
must(New("cpe:2.3:*:name:name:3.2:*:*:*:*:maven:*:*")),
must(New("cpe:2.3:*:name:name:3.2:*:*:*:*:jenkins:*:*")),
must(New("cpe:2.3:*:name:name:3.2:*:*:*:*:cloudbees_jenkins:*:*")),
must(New("cpe:2.3:*:name:name:3.2:*:*:*:*:*:*:*")),
must(New("cpe:2.3:*:*:name:3.2:*:*:*:*:java:*:*")),
must(New("cpe:2.3:*:*:name:3.2:*:*:*:*:maven:*:*")),
must(New("cpe:2.3:*:*:name:3.2:*:*:*:*:jenkins:*:*")),
must(New("cpe:2.3:*:*:name:3.2:*:*:*:*:cloudbees_jenkins:*:*")),
must(New("cpe:2.3:*:*:name:3.2:*:*:*:*:*:*:*")),
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
actual, err := Generate(&test.p)
if err != nil {
t.Fatalf("got an error while generating CPEs: %+v", err)
}
if len(actual) != len(test.expected) {
for _, e := range actual {
t.Errorf(" unexpected entry: %+v", e.BindToFmtString())
}
t.Fatalf("unexpected number of entries: %d", len(actual))
}
for idx, a := range actual {
e := test.expected[idx]
if a.BindToFmtString() != e.BindToFmtString() {
t.Errorf("mismatched entries @ %d:\n\texpected:%+v\n\t actual:%+v\n", idx, e.BindToFmtString(), a.BindToFmtString())
}
}
})
}
}
func TestMatchWithoutVersion(t *testing.T) {
tests := []struct {
name string
compare CPE
candidates []CPE
expected []CPE
compare pkg.CPE
candidates []pkg.CPE
expected []pkg.CPE
}{
{
name: "GoCase",
compare: must(New("cpe:2.3:*:python-requests:requests:2.3.0:*:*:*:*:python:*:*")),
candidates: []CPE{
must(New("cpe:2.3:a:python-requests:requests:2.2.1:*:*:*:*:*:*:*")),
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:*:*:*:*:*:*:*")),
},
expected: []CPE{
must(New("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:*:*:*:*:*:*:*")),
},
},
{
name: "IgnoreVersion",
compare: must(New("cpe:2.3:*:name:name:3.2:*:*:*:*:java:*:*")),
candidates: []CPE{
must(New("cpe:2.3:*:name:name:3.2:*:*:*:*:java:*:*")),
must(New("cpe:2.3:*:name:name:3.3:*:*:*:*:java:*:*")),
must(New("cpe:2.3:*:name:name:5.5:*:*:*:*:java:*:*")),
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:*:*")),
},
expected: []CPE{
must(New("cpe:2.3:*:name:name:3.2:*:*:*:*:java:*:*")),
must(New("cpe:2.3:*:name:name:3.3:*:*:*:*:java:*:*")),
must(New("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:*:*")),
},
},
{
name: "MatchByTargetSW",
compare: must(New("cpe:2.3:*:name:name:3.2:*:*:*:*:java:*:*")),
candidates: []CPE{
must(New("cpe:2.3:*:name:name:3.2:*:*:*:*:java:*:*")),
must(New("cpe:2.3:*:name:name:3.2:*:*:*:*:maven:*:*")),
must(New("cpe:2.3:*:name:name:3.2:*:*:*:*:jenkins:*:*")),
must(New("cpe:2.3:*:name:name:3.2:*:*:*:*:cloudbees_jenkins:*:*")),
must(New("cpe:2.3:*:name:name:3.2:*:*:*:*:*:*:*")),
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:*:*:*:*:*:*:*")),
},
expected: []CPE{
must(New("cpe:2.3:*:name:name:3.2:*:*:*:*:java:*:*")),
must(New("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:*:*:*:*:*:*:*")),
},
},
{
name: "MatchByName",
compare: must(New("cpe:2.3:*:name:name5:3.2:*:*:*:*:java:*:*")),
candidates: []CPE{
must(New("cpe:2.3:*:name:name1:3.2:*:*:*:*:java:*:*")),
must(New("cpe:2.3:*:name:name2:3.2:*:*:*:*:java:*:*")),
must(New("cpe:2.3:*:name:name3:3.2:*:*:*:*:java:*:*")),
must(New("cpe:2.3:*:name:name4:3.2:*:*:*:*:java:*:*")),
must(New("cpe:2.3:*:name:name5:3.2:*:*:*:*:*:*:*")),
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:*:*:*:*:*:*:*")),
},
expected: []CPE{
must(New("cpe:2.3:*:name:name5:3.2:*:*:*:*:*:*:*")),
expected: []pkg.CPE{
must(pkg.NewCPE("cpe:2.3:*:name:name5:3.2:*:*:*:*:*:*:*")),
},
},
{
name: "MatchByVendor",
compare: must(New("cpe:2.3:*:name3:name:3.2:*:*:*:*:java:*:*")),
candidates: []CPE{
must(New("cpe:2.3:*:name1:name:3.2:*:*:*:*:java:*:*")),
must(New("cpe:2.3:*:name3:name:3.2:*:*:*:*:jaba-no-bother:*:*")),
must(New("cpe:2.3:*:name3:name:3.2:*:*:*:*:java:*:*")),
must(New("cpe:2.3:*:name4:name:3.2:*:*:*:*:java:*:*")),
must(New("cpe:2.3:*:name5:name:3.2:*:*:*:*:*:*:*")),
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:*:*:*:*:*:*:*")),
},
expected: []CPE{
must(New("cpe:2.3:*:name3:name:3.2:*:*:*:*:java:*:*")),
expected: []pkg.CPE{
must(pkg.NewCPE("cpe:2.3:*:name3:name:3.2:*:*:*:*:java:*:*")),
},
},
{
name: "MatchAnyVendorOrTargetSW",
compare: must(New("cpe:2.3:*:*:name:3.2:*:*:*:*:*:*:*")),
candidates: []CPE{
must(New("cpe:2.3:*:name1:name:3.2:*:*:*:*:java:*:*")),
must(New("cpe:2.3:*:name3:name:3.2:*:*:*:*:jaba-no-bother:*:*")),
must(New("cpe:2.3:*:name3:name:3.2:*:*:*:*:java:*:*")),
must(New("cpe:2.3:*:name4:name:3.2:*:*:*:*:java:*:*")),
must(New("cpe:2.3:*:name5:name:3.2:*:*:*:*:*:*:*")),
must(New("cpe:2.3:*:name5:NOMATCH:3.2:*:*:*:*:*:*:*")),
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:*:*:*:*:*:*:*")),
},
expected: []CPE{
must(New("cpe:2.3:*:name1:name:3.2:*:*:*:*:java:*:*")),
must(New("cpe:2.3:*:name3:name:3.2:*:*:*:*:jaba-no-bother:*:*")),
must(New("cpe:2.3:*:name3:name:3.2:*:*:*:*:java:*:*")),
must(New("cpe:2.3:*:name4:name:3.2:*:*:*:*:java:*:*")),
must(New("cpe:2.3:*:name5:name: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:*:*:*:*:*:*:*")),
},
},
}

View file

@ -21,14 +21,14 @@ import (
"github.com/wagoodman/go-partybus"
)
func Catalog(userImageStr string, scopeOpt source.Scope) (source.Metadata, *pkg.Catalog, distro.Distro, error) {
func Catalog(userImageStr string, scopeOpt source.Scope) (source.Metadata, *pkg.Catalog, *distro.Distro, error) {
// handle explicit sbom input first
if strings.HasPrefix(userImageStr, "sbom:") {
// the user has explicitly hinted this is an sbom, if there is an issue return the error
filepath := strings.TrimPrefix(userImageStr, "sbom:")
sbomReader, err := os.Open(filepath)
if err != nil {
return source.Metadata{}, nil, distro.Distro{}, fmt.Errorf("unable to read sbom: %w", err)
return source.Metadata{}, nil, nil, fmt.Errorf("unable to read sbom: %w", err)
}
return syft.CatalogFromJSON(sbomReader)
} else if internal.IsPipedInput() && userImageStr == "" {
@ -47,7 +47,7 @@ func Catalog(userImageStr string, scopeOpt source.Scope) (source.Metadata, *pkg.
// attempt to parse as an image (left syft handle this)
theSource, catalog, theDistro, err := syft.Catalog(userImageStr, scopeOpt)
if err != nil {
return source.Metadata{}, nil, distro.Distro{}, err
return source.Metadata{}, nil, nil, err
}
return theSource.Metadata, catalog, theDistro, nil
}
@ -61,7 +61,7 @@ func FindVulnerabilities(provider vulnerability.Provider, userImageStr string, s
return FindVulnerabilitiesForCatalog(provider, theDistro, catalog), sourceMetadata, catalog, nil
}
func FindVulnerabilitiesForCatalog(provider vulnerability.Provider, d distro.Distro, catalog *pkg.Catalog) match.Matches {
func FindVulnerabilitiesForCatalog(provider vulnerability.Provider, d *distro.Distro, catalog *pkg.Catalog) match.Matches {
packages := make([]*pkg.Package, 0)
for p := range catalog.Enumerate() {
packages = append(packages, p)
@ -69,7 +69,7 @@ func FindVulnerabilitiesForCatalog(provider vulnerability.Provider, d distro.Dis
return FindVulnerabilitiesForPackage(provider, d, packages...)
}
func FindVulnerabilitiesForPackage(provider vulnerability.Provider, d distro.Distro, packages ...*pkg.Package) match.Matches {
func FindVulnerabilitiesForPackage(provider vulnerability.Provider, d *distro.Distro, packages ...*pkg.Package) match.Matches {
return matcher.FindMatches(provider, d, packages...)
}

View file

@ -19,7 +19,7 @@ func (m *Matcher) Type() match.MatcherType {
return match.ApkMatcher
}
func (m *Matcher) Match(store vulnerability.Provider, d distro.Distro, p *pkg.Package) ([]match.Match, error) {
func (m *Matcher) Match(store vulnerability.Provider, d *distro.Distro, p *pkg.Package) ([]match.Match, error) {
var matches = make([]match.Match, 0)
// map { CVE string : []match }

View file

@ -9,6 +9,13 @@ import (
"github.com/anchore/syft/syft/pkg"
)
func must(c pkg.CPE, e error) pkg.CPE {
if e != nil {
panic(e)
}
return c
}
type mockStore struct {
backend map[string]map[string][]v1.Vulnerability
}
@ -22,8 +29,7 @@ func (s *mockStore) GetVulnerability(namespace, name string) ([]v1.Vulnerability
}
func TestNoSecDBMatch(t *testing.T) {
// SecDB (matchesByPacakgeDistro) doesn't have a corresponding
// match to nvd, so no matches are returned
// SecDB (matchesByPackageDistro) doesn't have a corresponding match to nvd, so no matches are returned
store := mockStore{
backend: map[string]map[string][]v1.Vulnerability{
"nvd": {
@ -39,8 +45,7 @@ func TestNoSecDBMatch(t *testing.T) {
"alpine:3.12": {
"libvncserver": []v1.Vulnerability{
{
// ID doesn't match - this is the key
// for comparison in the matcher
// ID doesn't match - this is the key for comparison in the matcher
ID: "CVE-2020-2",
VersionConstraint: "<= 0.9.11",
VersionFormat: "apk",
@ -60,8 +65,11 @@ func TestNoSecDBMatch(t *testing.T) {
p := pkg.Package{
Name: "libvncserver",
Version: "0.9.9",
CPEs: []pkg.CPE{
must(pkg.NewCPE("cpe:2.3:a:*:libvncserver:0.9.9:*:*:*:*:*:*:*")),
},
}
matches, err := m.Match(provider, d, &p)
matches, err := m.Match(provider, &d, &p)
if err != nil {
t.Fatalf("failed to get matches: %+v", err)
@ -74,8 +82,7 @@ func TestNoSecDBMatch(t *testing.T) {
}
func TestMatches(t *testing.T) {
// NVD and Alpine's secDB both have the same CVE ID for the package
// so it matches
// NVD and Alpine's secDB both have the same CVE ID for the package so it matches
store := mockStore{
backend: map[string]map[string][]v1.Vulnerability{
"nvd": {
@ -91,8 +98,7 @@ func TestMatches(t *testing.T) {
"alpine:3.12": {
"libvncserver": []v1.Vulnerability{
{
// ID *does* match - this is the key
// for comparison in the matcher
// ID *does* match - this is the key for comparison in the matcher
ID: "CVE-2020-1",
VersionConstraint: "<= 0.9.11",
VersionFormat: "apk",
@ -112,8 +118,11 @@ func TestMatches(t *testing.T) {
p := pkg.Package{
Name: "libvncserver",
Version: "0.9.9",
CPEs: []pkg.CPE{
must(pkg.NewCPE("cpe:2.3:a:*:libvncserver:0.9.9:*:*:*:*:*:*:*")),
},
}
matches, err := m.Match(provider, d, &p)
matches, err := m.Match(provider, &d, &p)
if err != nil {
t.Fatalf("failed to get matches: %+v", err)

View file

@ -3,7 +3,6 @@ package common
import (
"testing"
"github.com/anchore/grype/grype/cpe"
"github.com/anchore/grype/grype/match"
"github.com/anchore/grype/grype/version"
"github.com/anchore/grype/grype/vulnerability"
@ -11,7 +10,7 @@ import (
"github.com/anchore/syft/syft/pkg"
)
func must(c cpe.CPE, e error) cpe.CPE {
func must(c pkg.CPE, e error) pkg.CPE {
if e != nil {
panic(e)
}
@ -36,29 +35,29 @@ func (pr *mockCPEProvider) stub() {
{
Constraint: version.MustGetConstraint("< 3.7.6", version.SemanticFormat),
ID: "CVE-2017-fake-1",
CPEs: []cpe.CPE{
must(cpe.New("cpe:2.3:*:activerecord:activerecord:*:*:*:*:*:rails:*:*")),
CPEs: []pkg.CPE{
must(pkg.NewCPE("cpe:2.3:*:activerecord:activerecord:*:*:*:*:*:rails:*:*")),
},
},
{
Constraint: version.MustGetConstraint("< 3.7.4", version.SemanticFormat),
ID: "CVE-2017-fake-2",
CPEs: []cpe.CPE{
must(cpe.New("cpe:2.3:*:activerecord:activerecord:*:*:*:*:*:ruby:*:*")),
CPEs: []pkg.CPE{
must(pkg.NewCPE("cpe:2.3:*:activerecord:activerecord:*:*:*:*:*:ruby:*:*")),
},
},
{
Constraint: version.MustGetConstraint("= 4.0.1", version.SemanticFormat),
ID: "CVE-2017-fake-3",
CPEs: []cpe.CPE{
must(cpe.New("cpe:2.3:*:couldntgetthisrightcouldyou:activerecord:4.0.1:*:*:*:*:*:*:*")),
CPEs: []pkg.CPE{
must(pkg.NewCPE("cpe:2.3:*:couldntgetthisrightcouldyou:activerecord:4.0.1:*:*:*:*:*:*:*")),
},
},
{
Constraint: version.MustGetConstraint("= 4.0.1", version.SemanticFormat),
ID: "CVE-2017-fake-3",
CPEs: []cpe.CPE{
must(cpe.New("cpe:2.3:*:couldntgetthisrightcouldyou:activerecord:4.0.1:*:*:*:*:*:*:*")),
CPEs: []pkg.CPE{
must(pkg.NewCPE("cpe:2.3:*:couldntgetthisrightcouldyou:activerecord:4.0.1:*:*:*:*:*:*:*")),
},
},
},
@ -66,15 +65,15 @@ func (pr *mockCPEProvider) stub() {
{
Constraint: version.MustGetConstraint("< 98SP3", version.UnknownFormat),
ID: "CVE-2017-fake-4",
CPEs: []cpe.CPE{
must(cpe.New("cpe:2.3:*:awesome:awesome:*:*:*:*:*:*:*:*")),
CPEs: []pkg.CPE{
must(pkg.NewCPE("cpe:2.3:*:awesome:awesome:*:*:*:*:*:*:*:*")),
},
},
},
}
}
func (pr *mockCPEProvider) GetByCPE(c cpe.CPE) ([]*vulnerability.Vulnerability, error) {
func (pr *mockCPEProvider) GetByCPE(c pkg.CPE) ([]*vulnerability.Vulnerability, error) {
return pr.data["nvd"][c.Product], nil
}
@ -87,6 +86,10 @@ func TestFindMatchesByPackageCPE(t *testing.T) {
{
name: "match from range",
p: pkg.Package{
CPEs: []pkg.CPE{
must(pkg.NewCPE("cpe:2.3:*:activerecord:activerecord:3.7.5:rando1:*:rando2:*:ruby:*:*")),
must(pkg.NewCPE("cpe:2.3:*:activerecord:activerecord:3.7.5:rando4:*:rando3:*:rails:*:*")),
},
Name: "activerecord",
Version: "3.7.5",
Language: pkg.Ruby,
@ -99,6 +102,10 @@ func TestFindMatchesByPackageCPE(t *testing.T) {
{
name: "multiple matches",
p: pkg.Package{
CPEs: []pkg.CPE{
must(pkg.NewCPE("cpe:2.3:*:activerecord:activerecord:3.7.3:rando1:*:rando2:*:ruby:*:*")),
must(pkg.NewCPE("cpe:2.3:*:activerecord:activerecord:3.7.3:rando4:*:rando3:*:rails:*:*")),
},
Name: "activerecord",
Version: "3.7.3",
Language: pkg.Ruby,
@ -112,6 +119,10 @@ func TestFindMatchesByPackageCPE(t *testing.T) {
{
name: "exact match",
p: pkg.Package{
CPEs: []pkg.CPE{
must(pkg.NewCPE("cpe:2.3:*:activerecord:activerecord:4.0.1:rando1:*:rando2:*:ruby:*:*")),
must(pkg.NewCPE("cpe:2.3:*:activerecord:activerecord:4.0.1:rando4:*:rando3:*:rails:*:*")),
},
Name: "activerecord",
Version: "4.0.1",
Language: pkg.Ruby,
@ -134,6 +145,9 @@ func TestFindMatchesByPackageCPE(t *testing.T) {
{
name: "fuzzy version match",
p: pkg.Package{
CPEs: []pkg.CPE{
must(pkg.NewCPE("cpe:2.3:*:awesome:awesome:98SE1:rando1:*:rando2:*:dunno:*:*")),
},
Name: "awesome",
Version: "98SE1",
},
@ -156,7 +170,7 @@ func TestFindMatchesByPackageCPE(t *testing.T) {
for _, a := range actual {
t.Errorf(" entry: %+v", a)
}
t.Fatalf("unexpected matches count: %d", len(actual))
t.Fatalf("unexpected matches count: %d != %d", len(actual), len(test.expected))
}
foundCVEs := internal.NewStringSet()

View file

@ -11,15 +11,18 @@ import (
"github.com/anchore/syft/syft/pkg"
)
func FindMatchesByPackageDistro(store vulnerability.ProviderByDistro, d distro.Distro, p *pkg.Package, upstreamMatcher match.MatcherType) ([]match.Match, error) {
func FindMatchesByPackageDistro(store vulnerability.ProviderByDistro, d *distro.Distro, p *pkg.Package, upstreamMatcher match.MatcherType) ([]match.Match, error) {
verObj, err := version.NewVersionFromPkg(p)
if err != nil {
return nil, fmt.Errorf("matcher failed to parse version pkg='%s' ver='%s': %w", p.Name, p.Version, err)
}
allPkgVulns, err := store.GetByDistro(d, p)
if err != nil {
return nil, fmt.Errorf("matcher failed to fetch distro='%s' pkg='%s': %w", d, p.Name, err)
var allPkgVulns []*vulnerability.Vulnerability
if d != nil {
allPkgVulns, err = store.GetByDistro(*d, p)
if err != nil {
return nil, fmt.Errorf("matcher failed to fetch distro='%s' pkg='%s': %w", d, p.Name, err)
}
}
matches := make([]match.Match, 0)

View file

@ -73,7 +73,7 @@ func TestFindMatchesByPackageDistro(t *testing.T) {
}
store := newMockProviderByDistro()
actual, err := FindMatchesByPackageDistro(store, d, &p, match.PythonMatcher)
actual, err := FindMatchesByPackageDistro(store, &d, &p, match.PythonMatcher)
if err != nil {
t.Fatalf("error while finding matches: %+v", err)
}

View file

@ -75,7 +75,7 @@ func (c *controller) trackMatcher() (*progress.Manual, *progress.Manual) {
return &packagesProcessed, &vulnerabilitiesDiscovered
}
func (c *controller) findMatches(provider vulnerability.Provider, d distro.Distro, packages ...*pkg.Package) match.Matches {
func (c *controller) findMatches(provider vulnerability.Provider, d *distro.Distro, packages ...*pkg.Package) match.Matches {
res := match.NewMatches()
packagesProcessed, vulnerabilitiesDiscovered := c.trackMatcher()
@ -106,7 +106,7 @@ func (c *controller) findMatches(provider vulnerability.Provider, d distro.Distr
return res
}
func FindMatches(provider vulnerability.Provider, d distro.Distro, packages ...*pkg.Package) match.Matches {
func FindMatches(provider vulnerability.Provider, d *distro.Distro, packages ...*pkg.Package) match.Matches {
return controllerInstance.findMatches(provider, d, packages...)
}

View file

@ -22,7 +22,7 @@ func (m *Matcher) Type() match.MatcherType {
return match.DpkgMatcher
}
func (m *Matcher) Match(store vulnerability.Provider, d distro.Distro, p *pkg.Package) ([]match.Match, error) {
func (m *Matcher) Match(store vulnerability.Provider, d *distro.Distro, p *pkg.Package) ([]match.Match, error) {
matches := make([]match.Match, 0)
sourceMatches, err := m.matchBySourceIndirection(store, d, p)
@ -40,7 +40,7 @@ func (m *Matcher) Match(store vulnerability.Provider, d distro.Distro, p *pkg.Pa
return matches, nil
}
func (m *Matcher) matchBySourceIndirection(store vulnerability.ProviderByDistro, d distro.Distro, p *pkg.Package) ([]match.Match, error) {
func (m *Matcher) matchBySourceIndirection(store vulnerability.ProviderByDistro, d *distro.Distro, p *pkg.Package) ([]match.Match, error) {
value, ok := p.Metadata.(pkg.DpkgMetadata)
if !ok {
return nil, fmt.Errorf("bad dpkg metadata type='%T'", value)

View file

@ -26,7 +26,7 @@ func TestMatcherDpkg_matchBySourceIndirection(t *testing.T) {
}
store := newMockProvider()
actual, err := matcher.matchBySourceIndirection(store, d, &p)
actual, err := matcher.matchBySourceIndirection(store, &d, &p)
if len(actual) != 2 {
t.Fatalf("unexpected indirect matches count: %d", len(actual))

View file

@ -19,7 +19,7 @@ func (m *Matcher) Type() match.MatcherType {
return match.JavaMatcher
}
func (m *Matcher) Match(store vulnerability.Provider, _ distro.Distro, p *pkg.Package) ([]match.Match, error) {
func (m *Matcher) Match(store vulnerability.Provider, _ *distro.Distro, p *pkg.Package) ([]match.Match, error) {
var matches = make([]match.Match, 0)
langMatches, err := common.FindMatchesByPackageLanguage(store, p.Language, p, m.Type())
if err != nil {

View file

@ -19,7 +19,7 @@ func (m *Matcher) Type() match.MatcherType {
return match.JavascriptMatcher
}
func (m *Matcher) Match(store vulnerability.Provider, _ distro.Distro, p *pkg.Package) ([]match.Match, error) {
func (m *Matcher) Match(store vulnerability.Provider, _ *distro.Distro, p *pkg.Package) ([]match.Match, error) {
var matches = make([]match.Match, 0)
langMatches, err := common.FindMatchesByPackageLanguage(store, p.Language, p, m.Type())
if err != nil {

View file

@ -10,5 +10,5 @@ import (
type Matcher interface {
PackageTypes() []pkg.Type
Type() match.MatcherType
Match(vulnerability.Provider, distro.Distro, *pkg.Package) ([]match.Match, error)
Match(vulnerability.Provider, *distro.Distro, *pkg.Package) ([]match.Match, error)
}

View file

@ -19,7 +19,7 @@ func (m *Matcher) Type() match.MatcherType {
return match.PythonMatcher
}
func (m *Matcher) Match(store vulnerability.Provider, _ distro.Distro, p *pkg.Package) ([]match.Match, error) {
func (m *Matcher) Match(store vulnerability.Provider, _ *distro.Distro, p *pkg.Package) ([]match.Match, error) {
var matches = make([]match.Match, 0)
langMatches, err := common.FindMatchesByPackageLanguage(store, p.Language, p, m.Type())
if err != nil {

View file

@ -27,7 +27,7 @@ func (m *Matcher) Type() match.MatcherType {
return match.RpmDBMatcher
}
func (m *Matcher) Match(store vulnerability.Provider, d distro.Distro, p *pkg.Package) ([]match.Match, error) {
func (m *Matcher) Match(store vulnerability.Provider, d *distro.Distro, p *pkg.Package) ([]match.Match, error) {
matches := make([]match.Match, 0)
sourceMatches, err := m.matchBySourceIndirection(store, d, p)
@ -45,7 +45,7 @@ func (m *Matcher) Match(store vulnerability.Provider, d distro.Distro, p *pkg.Pa
return matches, nil
}
func (m *Matcher) matchBySourceIndirection(store vulnerability.ProviderByDistro, d distro.Distro, p *pkg.Package) ([]match.Match, error) {
func (m *Matcher) matchBySourceIndirection(store vulnerability.ProviderByDistro, d *distro.Distro, p *pkg.Package) ([]match.Match, error) {
value, ok := p.Metadata.(pkg.RpmdbMetadata)
if !ok {
return nil, fmt.Errorf("bad rpmdb metadata type='%T'", value)

View file

@ -27,7 +27,7 @@ func TestMatcherDpkg_matchBySourceIndirection(t *testing.T) {
}
store := newMockProvider()
actual, err := matcher.matchBySourceIndirection(store, d, &p)
actual, err := matcher.matchBySourceIndirection(store, &d, &p)
if len(actual) != 2 {
t.Fatalf("unexpected indirect matches count: %d", len(actual))
@ -87,7 +87,7 @@ func TestMatcherDpkg_matchBySourceIndirection_ignoreSource(t *testing.T) {
}
store := newMockProvider()
actual, err := matcher.matchBySourceIndirection(store, d, &p)
actual, err := matcher.matchBySourceIndirection(store, &d, &p)
if len(actual) != 0 {
t.Fatalf("unexpected indirect matches count: %d", len(actual))

View file

@ -19,7 +19,7 @@ func (m *Matcher) Type() match.MatcherType {
return match.RubyGemMatcher
}
func (m *Matcher) Match(store vulnerability.Provider, _ distro.Distro, p *pkg.Package) ([]match.Match, error) {
func (m *Matcher) Match(store vulnerability.Provider, _ *distro.Distro, p *pkg.Package) ([]match.Match, error) {
var matches = make([]match.Match, 0)
langMatches, err := common.FindMatchesByPackageLanguage(store, p.Language, p, m.Type())
if err != nil {

View file

@ -38,7 +38,7 @@ type MatchDetails struct {
}
// NewDocument creates and populates a new Document struct, representing the populated JSON document.
func NewDocument(catalog *pkg.Catalog, d distro.Distro, srcMetadata source.Metadata, matches match.Matches, metadataProvider vulnerability.MetadataProvider) (Document, error) {
func NewDocument(catalog *pkg.Catalog, d *distro.Distro, srcMetadata source.Metadata, matches match.Matches, metadataProvider vulnerability.MetadataProvider) (Document, error) {
// we must preallocate the findings to ensure the JSON document does not show "null" when no matches are found
var findings = make([]Match, 0)
for m := range matches.Enumerate() {

View file

@ -17,13 +17,13 @@ import (
type Presenter struct {
matches match.Matches
catalog *pkg.Catalog
distro distro.Distro
distro *distro.Distro
srcMetadata source.Metadata
metadataProvider vulnerability.MetadataProvider
}
// NewPresenter is a *Presenter constructor
func NewPresenter(matches match.Matches, catalog *pkg.Catalog, d distro.Distro, srcMetadata source.Metadata, metadataProvider vulnerability.MetadataProvider) *Presenter {
func NewPresenter(matches match.Matches, catalog *pkg.Catalog, d *distro.Distro, srcMetadata source.Metadata, metadataProvider vulnerability.MetadataProvider) *Presenter {
return &Presenter{
matches: matches,
catalog: catalog,

View file

@ -160,7 +160,7 @@ func TestJsonImgsPresenter(t *testing.T) {
t.Fatalf("failed to create scope: %+v", err)
}
pres := NewPresenter(matches, catalog, d, theSource.Metadata, newMetadataMock())
pres := NewPresenter(matches, catalog, &d, theSource.Metadata, newMetadataMock())
// TODO: add a constructor for a match.Match when the data is better shaped
@ -276,7 +276,7 @@ func TestJsonDirsPresenter(t *testing.T) {
t.Fatalf("could not make distro: %+v", err)
}
pres := NewPresenter(matches, catalog, d, s.Metadata, newMetadataMock())
pres := NewPresenter(matches, catalog, &d, s.Metadata, newMetadataMock())
// TODO: add a constructor for a match.Match when the data is better shaped
@ -328,7 +328,7 @@ func TestEmptyJsonPresenter(t *testing.T) {
t.Fatalf("could not make distro: %+v", err)
}
pres := NewPresenter(matches, catalog, d, theSource.Metadata, nil)
pres := NewPresenter(matches, catalog, &d, theSource.Metadata, nil)
// run presenter
if err = pres.Present(&buffer); err != nil {

View file

@ -34,6 +34,8 @@
],
"licenses": null,
"language": "",
"cpes": [],
"purl": "",
"metadataType": ""
}
},
@ -69,6 +71,8 @@
],
"licenses": null,
"language": "",
"cpes": [],
"purl": "",
"metadataType": ""
}
},
@ -99,6 +103,8 @@
],
"licenses": null,
"language": "",
"cpes": [],
"purl": "",
"metadataType": ""
}
}

View file

@ -35,6 +35,8 @@
],
"licenses": null,
"language": "",
"cpes": [],
"purl": "",
"metadataType": ""
}
},
@ -71,6 +73,8 @@
],
"licenses": null,
"language": "",
"cpes": [],
"purl": "",
"metadataType": ""
}
},
@ -102,6 +106,8 @@
],
"licenses": null,
"language": "",
"cpes": [],
"purl": "",
"metadataType": ""
}
}

View file

@ -22,7 +22,7 @@ type Presenter interface {
}
// GetPresenter retrieves a Presenter that matches a CLI option
func GetPresenter(option Option, matches match.Matches, catalog *pkg.Catalog, d distro.Distro, srcMetadata source.Metadata, metadataProvider vulnerability.MetadataProvider) Presenter {
func GetPresenter(option Option, matches match.Matches, catalog *pkg.Catalog, d *distro.Distro, srcMetadata source.Metadata, metadataProvider vulnerability.MetadataProvider) Presenter {
switch option {
case JSONPresenter:
return json.NewPresenter(matches, catalog, d, srcMetadata, metadataProvider)

View file

@ -3,7 +3,6 @@ package version
import (
"fmt"
"github.com/anchore/grype/grype/cpe"
"github.com/anchore/syft/syft/pkg"
)
@ -14,7 +13,7 @@ type Version struct {
}
type rich struct {
cpeVers []cpe.CPE
cpeVers []pkg.CPE
semVer *semanticVersion
debVer *debVersion
rpmVer *rpmVersion
@ -39,12 +38,8 @@ func NewVersionFromPkg(p *pkg.Package) (*Version, error) {
if err != nil {
return nil, err
}
cpes, err := cpe.Generate(p)
if err != nil {
return nil, err
}
ver.rich.cpeVers = cpes
ver.rich.cpeVers = p.CPEs
return ver, nil
}
@ -72,7 +67,7 @@ func (v *Version) populate() error {
return fmt.Errorf("no rich version populated (format=%s)", v.Format)
}
func (v Version) CPEs() []cpe.CPE {
func (v Version) CPEs() []pkg.CPE {
return v.rich.cpeVers
}

View file

@ -1,7 +1,6 @@
package vulnerability
import (
"github.com/anchore/grype/grype/cpe"
"github.com/anchore/syft/syft/distro"
"github.com/anchore/syft/syft/pkg"
)
@ -21,7 +20,7 @@ type ProviderByLanguage interface {
}
type ProviderByCPE interface {
GetByCPE(cpe.CPE) ([]*Vulnerability, error)
GetByCPE(pkg.CPE) ([]*Vulnerability, error)
}
type MetadataProvider interface {

View file

@ -70,7 +70,7 @@ func (pr *StoreAdapter) GetByLanguage(l pkg.Language, p *pkg.Package) ([]*Vulner
return vulns, nil
}
func (pr *StoreAdapter) GetByCPE(requestCPE cpe.CPE) ([]*Vulnerability, error) {
func (pr *StoreAdapter) GetByCPE(requestCPE pkg.CPE) ([]*Vulnerability, error) {
vulns := make([]*Vulnerability, 0)
namespaces := cpeNamespaces()

View file

@ -3,7 +3,6 @@ package vulnerability
import (
"testing"
"github.com/anchore/grype/grype/cpe"
"github.com/go-test/deep"
"github.com/anchore/grype/grype/version"
@ -54,7 +53,7 @@ func TestGetByDistro(t *testing.T) {
}
func must(c cpe.CPE, e error) cpe.CPE {
func must(c pkg.CPE, e error) pkg.CPE {
if e != nil {
panic(e)
}
@ -65,19 +64,19 @@ func TestGetByCPE(t *testing.T) {
tests := []struct {
name string
cpe cpe.CPE
cpe pkg.CPE
expected []Vulnerability
err bool
}{
{
name: "match from name and target SW",
cpe: must(cpe.New("cpe:2.3:*:activerecord:activerecord:*:*:*:*:*:ruby:*:*")),
cpe: must(pkg.NewCPE("cpe:2.3:*:activerecord:activerecord:*:*:*:*:*:ruby:*:*")),
expected: []Vulnerability{
{
Constraint: version.MustGetConstraint("< 3.7.4", version.UnknownFormat),
ID: "CVE-2014-fake-4",
CPEs: []cpe.CPE{
must(cpe.New("cpe:2.3:*:activerecord:activerecord:*:*:something:*:*:ruby:*:*")),
CPEs: []pkg.CPE{
must(pkg.NewCPE("cpe:2.3:*:activerecord:activerecord:*:*:something:*:*:ruby:*:*")),
},
},
},
@ -85,20 +84,20 @@ func TestGetByCPE(t *testing.T) {
{
name: "match from vendor & name",
cpe: must(cpe.New("cpe:2.3:*:activerecord:activerecord:*:*:*:*:*:*:*:*")),
cpe: must(pkg.NewCPE("cpe:2.3:*:activerecord:activerecord:*:*:*:*:*:*:*:*")),
expected: []Vulnerability{
{
Constraint: version.MustGetConstraint("< 3.7.6", version.UnknownFormat),
ID: "CVE-2014-fake-3",
CPEs: []cpe.CPE{
must(cpe.New("cpe:2.3:*:activerecord:activerecord:*:*:*:*:*:rails:*:*")),
CPEs: []pkg.CPE{
must(pkg.NewCPE("cpe:2.3:*:activerecord:activerecord:*:*:*:*:*:rails:*:*")),
},
},
{
Constraint: version.MustGetConstraint("< 3.7.4", version.UnknownFormat),
ID: "CVE-2014-fake-4",
CPEs: []cpe.CPE{
must(cpe.New("cpe:2.3:*:activerecord:activerecord:*:*:something:*:*:ruby:*:*")),
CPEs: []pkg.CPE{
must(pkg.NewCPE("cpe:2.3:*:activerecord:activerecord:*:*:something:*:*:ruby:*:*")),
},
},
},
@ -106,7 +105,7 @@ func TestGetByCPE(t *testing.T) {
{
name: "dont allow any name",
cpe: must(cpe.New("cpe:2.3:*:couldntgetthisrightcouldyou:*:*:*:*:*:*:*:*:*")),
cpe: must(pkg.NewCPE("cpe:2.3:*:couldntgetthisrightcouldyou:*:*:*:*:*:*:*:*:*")),
err: true,
},
}

View file

@ -4,13 +4,13 @@ import (
"fmt"
v1 "github.com/anchore/grype-db/pkg/db/v1"
"github.com/anchore/grype/grype/cpe"
"github.com/anchore/grype/grype/version"
"github.com/anchore/syft/syft/pkg"
)
type Vulnerability struct {
Constraint version.Constraint
CPEs []cpe.CPE
CPEs []pkg.CPE
ID string
RecordSource string
FixedInVersion string
@ -27,7 +27,7 @@ func NewVulnerability(vuln v1.Vulnerability) (*Vulnerability, error) {
return &Vulnerability{
Constraint: constraint,
ID: vuln.ID,
CPEs: make([]cpe.CPE, 0),
CPEs: make([]pkg.CPE, 0),
RecordSource: vuln.RecordSource,
FixedInVersion: vuln.FixedInVersion,
}, nil