From 396cc0aea758c220570cf3f1432f4948e6509cc9 Mon Sep 17 00:00:00 2001 From: William Murphy Date: Wed, 7 Feb 2024 14:28:48 -0500 Subject: [PATCH] Bump Syft in Grype to pull in unmarshaling fix (#1703) * WIP: package builds but tests do not Signed-off-by: Will Murphy * WIP: some unit tests compile Signed-off-by: Will Murphy * WIP: unit tests compile but do not pass Signed-off-by: Will Murphy * Units passing with some changes to syft Signed-off-by: Will Murphy * fix: excludes plus bad sbom should not suppress error Signed-off-by: Will Murphy * add conan entry v2 package test Signed-off-by: Will Murphy * bump syft again Signed-off-by: Will Murphy * chore: fix compiler error in integration tests Signed-off-by: Will Murphy * chore: remove erlang OTP from package types that must be seen in test image Signed-off-by: Will Murphy * bump syft version used Signed-off-by: Alex Goodman --------- Signed-off-by: Will Murphy Signed-off-by: Alex Goodman Co-authored-by: Alex Goodman --- go.mod | 14 +-- go.sum | 27 +++--- grype/cpe/cpe.go | 6 +- grype/cpe/cpe_test.go | 96 +++++++++---------- grype/db/vulnerability_provider.go | 10 +- grype/db/vulnerability_provider_test.go | 16 ++-- grype/matcher/apk/matcher_test.go | 30 +++--- grype/matcher/golang/matcher_test.go | 4 +- grype/pkg/golang_metadata.go | 13 ++- grype/pkg/package.go | 6 +- grype/pkg/package_test.go | 60 +++++++++--- grype/pkg/provider.go | 7 +- grype/pkg/provider_test.go | 16 +++- grype/pkg/purl_provider.go | 2 +- grype/pkg/qualifier/platformcpe/qualifier.go | 12 +-- grype/pkg/syft_sbom_provider_test.go | 18 ++-- grype/pkg/test-fixtures/bad-sbom.json | 1 + grype/pkg/upstream_package.go | 6 +- grype/pkg/upstream_package_test.go | 10 +- grype/presenter/internal/test_helpers.go | 24 +++-- grype/presenter/models/package.go | 2 +- grype/search/cpe.go | 10 +- grype/search/cpe_test.go | 66 ++++++------- grype/search/only_vulnerable_targets.go | 2 +- grype/vulnerability_matcher_test.go | 2 +- .../compare_sbom_input_vs_lib_test.go | 1 + test/integration/match_by_image_test.go | 10 +- 27 files changed, 268 insertions(+), 203 deletions(-) create mode 100644 grype/pkg/test-fixtures/bad-sbom.json diff --git a/go.mod b/go.mod index 66dd394b197..fb090aafbeb 100644 --- a/go.mod +++ b/go.mod @@ -8,13 +8,13 @@ require ( github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d github.com/adrg/xdg v0.4.0 github.com/anchore/bubbly v0.0.0-20231115134915-def0aba654a9 - github.com/anchore/clio v0.0.0-20231016125544-c98a83e1c7fc + github.com/anchore/clio v0.0.0-20240131202212-9eba61247448 github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 github.com/anchore/go-version v1.2.2-0.20210903204242-51efa5b487c4 - github.com/anchore/packageurl-go v0.1.1-0.20230104203445-02e0a6721501 - github.com/anchore/stereoscope v0.0.1 - github.com/anchore/syft v0.103.1 + github.com/anchore/packageurl-go v0.1.1-0.20240202171727-877e1747d426 + github.com/anchore/stereoscope v0.0.2-0.20240202153536-bfa15e446f06 + github.com/anchore/syft v0.103.2-0.20240207163149-da31eed6374d github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46 github.com/bmatcuk/doublestar/v2 v2.0.4 github.com/charmbracelet/bubbletea v0.25.0 @@ -89,7 +89,7 @@ require ( github.com/becheran/wildmatch-go v1.0.0 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/bmatcuk/doublestar/v4 v4.6.1 // indirect - github.com/charmbracelet/bubbles v0.17.1 // indirect + github.com/charmbracelet/bubbles v0.18.0 // indirect github.com/charmbracelet/harmonica v0.2.0 // indirect github.com/cloudflare/circl v1.3.7 // indirect github.com/containerd/cgroups v1.1.0 // indirect @@ -194,7 +194,7 @@ require ( github.com/pkg/profile v1.7.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect - github.com/rivo/uniseg v0.2.0 // indirect + github.com/rivo/uniseg v0.4.6 // indirect github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/saferwall/pe v1.4.8 // indirect github.com/sagikazarmark/locafero v0.3.0 // indirect @@ -234,7 +234,7 @@ require ( go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect golang.org/x/crypto v0.18.0 // indirect - golang.org/x/mod v0.14.0 // indirect + golang.org/x/mod v0.15.0 // indirect golang.org/x/net v0.20.0 // indirect golang.org/x/oauth2 v0.15.0 // indirect golang.org/x/sync v0.5.0 // indirect diff --git a/go.sum b/go.sum index f17d888868f..dc33b669628 100644 --- a/go.sum +++ b/go.sum @@ -235,8 +235,8 @@ github.com/anchore/archiver/v3 v3.5.2 h1:Bjemm2NzuRhmHy3m0lRe5tNoClB9A4zYyDV58Pa github.com/anchore/archiver/v3 v3.5.2/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4= github.com/anchore/bubbly v0.0.0-20231115134915-def0aba654a9 h1:p0ZIe0htYOX284Y4axJaGBvXHU0VCCzLN5Wf5XbKStU= github.com/anchore/bubbly v0.0.0-20231115134915-def0aba654a9/go.mod h1:3ZsFB9tzW3vl4gEiUeuSOMDnwroWxIxJelOOHUp8dSw= -github.com/anchore/clio v0.0.0-20231016125544-c98a83e1c7fc h1:A1KFO+zZZmbNlz1+WKsCF0RKVx6XRoxsAG3lrqH9hUQ= -github.com/anchore/clio v0.0.0-20231016125544-c98a83e1c7fc/go.mod h1:QeWvNzxsrUNxcs6haQo3OtISfXUXW0qAuiG4EQiz0GU= +github.com/anchore/clio v0.0.0-20240131202212-9eba61247448 h1:ZgecmkxhH5im+9jPs7Ra1Thmv/p4IBDsoCFD6W8pENg= +github.com/anchore/clio v0.0.0-20240131202212-9eba61247448/go.mod h1:t5Mld8naKcG8RTPjW/2n7bfyBKFl1A6PvtXw+v64gK0= github.com/anchore/fangs v0.0.0-20231201140849-5075d28d6d8b h1:L/djgY7ZbZ/38+wUtdkk398W3PIBJLkt1N8nU/7e47A= github.com/anchore/fangs v0.0.0-20231201140849-5075d28d6d8b/go.mod h1:TLcE0RE5+8oIx2/NPWem/dq1DeaMoC+fPEH7hoSzPLo= github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a h1:nJ2G8zWKASyVClGVgG7sfM5mwoZlZ2zYpIzN2OhjWkw= @@ -249,12 +249,12 @@ github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 h1:VzprUTpc0v github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04/go.mod h1:6dK64g27Qi1qGQZ67gFmBFvEHScy0/C8qhQhNe5B5pQ= github.com/anchore/go-version v1.2.2-0.20210903204242-51efa5b487c4 h1:rmZG77uXgE+o2gozGEBoUMpX27lsku+xrMwlmBZJtbg= github.com/anchore/go-version v1.2.2-0.20210903204242-51efa5b487c4/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E= -github.com/anchore/packageurl-go v0.1.1-0.20230104203445-02e0a6721501 h1:AV7qjwMcM4r8wFhJq3jLRztew3ywIyPTRapl2T1s9o8= -github.com/anchore/packageurl-go v0.1.1-0.20230104203445-02e0a6721501/go.mod h1:Blo6OgJNiYF41ufcgHKkbCKF2MDOMlrqhXv/ij6ocR4= -github.com/anchore/stereoscope v0.0.1 h1:OxF7PaxMltnAxjLnDMyka+SKRIQar/bBkDdavsnjyxM= -github.com/anchore/stereoscope v0.0.1/go.mod h1:IylG7ofLoUKHwS1XDF6rPhOmaE3GgpAgsMdvvYfooTU= -github.com/anchore/syft v0.103.1 h1:E5VJoNeFDh8AOetPkT8h5tyl8GmCRV8aeA1XZlwxS4U= -github.com/anchore/syft v0.103.1/go.mod h1:Ph25SA9kx4nJS8XlgTmI4/FvPCX7PbRyA5LBdlcH1zQ= +github.com/anchore/packageurl-go v0.1.1-0.20240202171727-877e1747d426 h1:agoiZchSf1Nnnos1azwIg5hk5Ao9TzZNBD9++AChGEg= +github.com/anchore/packageurl-go v0.1.1-0.20240202171727-877e1747d426/go.mod h1:Blo6OgJNiYF41ufcgHKkbCKF2MDOMlrqhXv/ij6ocR4= +github.com/anchore/stereoscope v0.0.2-0.20240202153536-bfa15e446f06 h1:3NAS33Bqrw87wckTff6/yXYDL1h3Wm6OiqaR1kcvW10= +github.com/anchore/stereoscope v0.0.2-0.20240202153536-bfa15e446f06/go.mod h1:uydT2ful8TY7Hr1WH1V1ZecSq/2TqXpAsGkMiy7lxD0= +github.com/anchore/syft v0.103.2-0.20240207163149-da31eed6374d h1:YivlSmLJgnOdxAhKitf5sjYIsPrBFUn5nbAtYuanv7o= +github.com/anchore/syft v0.103.2-0.20240207163149-da31eed6374d/go.mod h1:Sp1juSmwcyo1fg1r7YE8TYLgRG+mcA0IKDeJcrGF8Dk= 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.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= @@ -304,8 +304,8 @@ github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/charmbracelet/bubbles v0.17.1 h1:0SIyjOnkrsfDo88YvPgAWvZMwXe26TP6drRvmkjyUu4= -github.com/charmbracelet/bubbles v0.17.1/go.mod h1:9HxZWlkCqz2PRwsCbYl7a3KXvGzFaDHpYbSYMJ+nE3o= +github.com/charmbracelet/bubbles v0.18.0 h1:PYv1A036luoBGroX6VWjQIE9Syf2Wby2oOl/39KLfy0= +github.com/charmbracelet/bubbles v0.18.0/go.mod h1:08qhZhtIwzgrtBjAcJnij1t1H0ZRjwHyGsy6AL11PSw= github.com/charmbracelet/bubbletea v0.25.0 h1:bAfwk7jRz7FKFl9RzlIULPkStffg5k6pNt5dywy4TcM= github.com/charmbracelet/bubbletea v0.25.0/go.mod h1:EN3QDR1T5ZdWmdfDzYcqOCAps45+QIJbLOBxmVNWNNg= github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ= @@ -866,8 +866,9 @@ github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0ua github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.6 h1:Sovz9sDSwbOz9tgUy8JpT+KgCkPYJEN/oYzlJiYTNLg= +github.com/rivo/uniseg v0.4.6/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= @@ -1115,8 +1116,8 @@ golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= +golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= diff --git a/grype/cpe/cpe.go b/grype/cpe/cpe.go index 7e7874b9427..99d288bb4b5 100644 --- a/grype/cpe/cpe.go +++ b/grype/cpe/cpe.go @@ -10,7 +10,7 @@ import ( func NewSlice(cpeStrs ...string) ([]cpe.CPE, error) { var cpes []cpe.CPE for _, c := range cpeStrs { - value, err := cpe.New(c) + value, err := cpe.New(c, "") if err != nil { log.Warnf("excluding invalid CPE %q: %v", c, err) continue @@ -23,9 +23,9 @@ func NewSlice(cpeStrs ...string) ([]cpe.CPE, error) { func MatchWithoutVersion(c cpe.CPE, candidates []cpe.CPE) []cpe.CPE { matches := make([]cpe.CPE, 0) - a := wfn.Attributes(c) + a := wfn.Attributes(c.Attributes) for _, candidate := range candidates { - canCopy := wfn.Attributes(candidate) + canCopy := wfn.Attributes(candidate.Attributes) if a.MatchWithoutVersion(&canCopy) { matches = append(matches, candidate) } diff --git a/grype/cpe/cpe_test.go b/grype/cpe/cpe_test.go index df1b57eb2ae..f259ee097df 100644 --- a/grype/cpe/cpe_test.go +++ b/grype/cpe/cpe_test.go @@ -17,88 +17,88 @@ func TestMatchWithoutVersion(t *testing.T) { }{ { name: "GoCase", - compare: cpe.Must("cpe:2.3:*:python-requests:requests:2.3.0:*:*:*:*:python:*:*"), + 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:*:*:*:*:*:*:*"), + cpe.Must("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:*:*:*:*:*:*:*"), + cpe.Must("cpe:2.3:a:python-requests:requests:2.2.1:*:*:*:*:*:*:*", ""), }, }, { name: "IgnoreVersion", - compare: cpe.Must("cpe:2.3:*:name:name:3.2:*:*:*:*: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:*:*"), + 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: []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:*:*"), + 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: cpe.Must("cpe:2.3:*:name:name:3.2:*:*:*:*: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.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:*:*:*:*:*:*:*"), + 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: []cpe.CPE{ - cpe.Must("cpe:2.3:*:name:name:3.2:*:*:*:*:java:*:*"), - cpe.Must("cpe:2.3:*:name:name:3.2:*:*:*:*:*:*:*"), + cpe.Must("cpe:2.3:*:name:name:3.2:*:*:*:*:java:*:*", ""), + cpe.Must("cpe:2.3:*:name:name:3.2:*:*:*:*:*:*:*", ""), }, }, { name: "MatchByName", - compare: cpe.Must("cpe:2.3:*:name:name5:3.2:*:*:*:*:java:*:*"), + 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:*:*:*:*:*:*:*"), + 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: []cpe.CPE{ - cpe.Must("cpe:2.3:*:name:name5:3.2:*:*:*:*:*:*:*"), + cpe.Must("cpe:2.3:*:name:name5:3.2:*:*:*:*:*:*:*", ""), }, }, { name: "MatchByVendor", - compare: cpe.Must("cpe:2.3:*:name3:name:3.2:*:*:*:*:java:*:*"), + 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:*:*:*:*:*:*:*"), + 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: []cpe.CPE{ - cpe.Must("cpe:2.3:*:name3:name:3.2:*:*:*:*:java:*:*"), + cpe.Must("cpe:2.3:*:name3:name:3.2:*:*:*:*:java:*:*", ""), }, }, { name: "MatchAnyVendorOrTargetSW", - compare: cpe.Must("cpe:2.3:*:*:name: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:*:*:*:*:*:*:*"), + 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: []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:*: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:*:*:*:*:*:*:*", ""), }, }, } @@ -109,17 +109,17 @@ func TestMatchWithoutVersion(t *testing.T) { if len(actual) != len(test.expected) { for _, e := range actual { - t.Errorf(" unexpected entry: %+v", e.BindToFmtString()) + t.Errorf(" unexpected entry: %+v", e.Attributes.BindToFmtString()) } t.Fatalf("unexpected number of entries: %d", len(actual)) } for idx, a := range actual { e := test.expected[idx] - if a.BindToFmtString() != e.BindToFmtString() { + if a.Attributes.BindToFmtString() != e.Attributes.BindToFmtString() { dmp := diffmatchpatch.New() - diffs := dmp.DiffMain(a.BindToFmtString(), e.BindToFmtString(), true) - t.Errorf("mismatched entries @ %d:\n\texpected:%+v\n\t actual:%+v\n\t diff:%+v\n", idx, e.BindToFmtString(), a.BindToFmtString(), dmp.DiffPrettyText(diffs)) + diffs := dmp.DiffMain(a.Attributes.BindToFmtString(), e.Attributes.BindToFmtString(), true) + t.Errorf("mismatched entries @ %d:\n\texpected:%+v\n\t actual:%+v\n\t diff:%+v\n", idx, e.Attributes.BindToFmtString(), a.Attributes.BindToFmtString(), dmp.DiffPrettyText(diffs)) } } }) diff --git a/grype/db/vulnerability_provider.go b/grype/db/vulnerability_provider.go index 0b9d7959745..faff3264016 100644 --- a/grype/db/vulnerability_provider.go +++ b/grype/db/vulnerability_provider.go @@ -141,17 +141,17 @@ func (pr *VulnerabilityProvider) GetByCPE(requestCPE cpe.CPE) ([]vulnerability.V return nil, nil } - if requestCPE.Product == wfn.Any || requestCPE.Product == wfn.NA { + if requestCPE.Attributes.Product == wfn.Any || requestCPE.Attributes.Product == wfn.NA { return nil, fmt.Errorf("product name is required") } for _, ns := range namespaces { - allPkgVulns, err := pr.reader.SearchForVulnerabilities(ns.String(), ns.Resolver().Normalize(requestCPE.Product)) + allPkgVulns, err := pr.reader.SearchForVulnerabilities(ns.String(), ns.Resolver().Normalize(requestCPE.Attributes.Product)) if err != nil { - return nil, fmt.Errorf("provider failed to fetch namespace=%q product=%q: %w", ns, requestCPE.Product, err) + return nil, fmt.Errorf("provider failed to fetch namespace=%q product=%q: %w", ns, requestCPE.Attributes.Product, err) } - normalizedRequestCPE, err := cpe.New(ns.Resolver().Normalize(requestCPE.BindToFmtString())) + normalizedRequestCPE, err := cpe.New(ns.Resolver().Normalize(requestCPE.Attributes.BindToFmtString()), requestCPE.Source) if err != nil { normalizedRequestCPE = requestCPE @@ -169,7 +169,7 @@ func (pr *VulnerabilityProvider) GetByCPE(requestCPE cpe.CPE) ([]vulnerability.V if len(candidateMatchCpes) > 0 { vulnObj, err := vulnerability.NewVulnerability(vuln) if err != nil { - return nil, fmt.Errorf("provider failed to inflate vulnerability record (namespace=%q id=%q cpe=%q): %w", vuln.Namespace, vuln.ID, requestCPE.BindToFmtString(), err) + return nil, fmt.Errorf("provider failed to inflate vulnerability record (namespace=%q id=%q cpe=%q): %w", vuln.Namespace, vuln.ID, requestCPE.Attributes.BindToFmtString(), err) } vulnObj.CPEs = candidateMatchCpes diff --git a/grype/db/vulnerability_provider_test.go b/grype/db/vulnerability_provider_test.go index bbd946a309b..26163b8fdf3 100644 --- a/grype/db/vulnerability_provider_test.go +++ b/grype/db/vulnerability_provider_test.go @@ -84,13 +84,13 @@ func Test_GetByCPE(t *testing.T) { }{ { name: "match from name and target SW", - cpe: cpe.Must("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: []cpe.CPE{ - cpe.Must("cpe:2.3:*:activerecord:activerecord:*:*:something:*:*:ruby:*:*"), + cpe.Must("cpe:2.3:*:activerecord:activerecord:*:*:something:*:*:ruby:*:*", ""), }, Namespace: "nvd:cpe", PackageQualifiers: []qualifier.Qualifier{}, @@ -100,13 +100,13 @@ func Test_GetByCPE(t *testing.T) { }, { name: "match with normalization", - cpe: cpe.Must("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: []cpe.CPE{ - cpe.Must("cpe:2.3:*:activerecord:activerecord:*:*:something:*:*:ruby:*:*"), + cpe.Must("cpe:2.3:*:activerecord:activerecord:*:*:something:*:*:ruby:*:*", ""), }, Namespace: "nvd:cpe", PackageQualifiers: []qualifier.Qualifier{}, @@ -116,13 +116,13 @@ func Test_GetByCPE(t *testing.T) { }, { name: "match from vendor & name", - cpe: cpe.Must("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: []cpe.CPE{ - cpe.Must("cpe:2.3:*:activerecord:activerecord:*:*:*:*:*:rails:*:*"), + cpe.Must("cpe:2.3:*:activerecord:activerecord:*:*:*:*:*:rails:*:*", ""), }, Namespace: "nvd:cpe", PackageQualifiers: []qualifier.Qualifier{}, @@ -132,7 +132,7 @@ func Test_GetByCPE(t *testing.T) { Constraint: version.MustGetConstraint("< 3.7.4", version.UnknownFormat), ID: "CVE-2014-fake-4", CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:*:activerecord:activerecord:*:*:something:*:*:ruby:*:*"), + cpe.Must("cpe:2.3:*:activerecord:activerecord:*:*:something:*:*:ruby:*:*", ""), }, Namespace: "nvd:cpe", PackageQualifiers: []qualifier.Qualifier{}, @@ -143,7 +143,7 @@ func Test_GetByCPE(t *testing.T) { { name: "dont allow any name", - cpe: cpe.Must("cpe:2.3:*:couldntgetthisrightcouldyou:*:*:*:*:*:*:*:*:*"), + cpe: cpe.Must("cpe:2.3:*:couldntgetthisrightcouldyou:*:*:*:*:*:*:*:*:*", ""), err: true, }, } diff --git a/grype/matcher/apk/matcher_test.go b/grype/matcher/apk/matcher_test.go index 569b94a07fb..1c117cc1a7f 100644 --- a/grype/matcher/apk/matcher_test.go +++ b/grype/matcher/apk/matcher_test.go @@ -82,7 +82,7 @@ func TestSecDBOnlyMatch(t *testing.T) { Version: "0.9.9", Type: syftPkg.ApkPkg, CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:a:*:libvncserver:0.9.9:*:*:*:*:*:*:*"), + cpe.Must("cpe:2.3:a:*:libvncserver:0.9.9:*:*:*:*:*:*:*", ""), }, } @@ -168,7 +168,7 @@ func TestBothSecdbAndNvdMatches(t *testing.T) { Version: "0.9.9", Type: syftPkg.ApkPkg, CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:a:*:libvncserver:0.9.9:*:*:*:*:*:*:*"), + cpe.Must("cpe:2.3:a:*:libvncserver:0.9.9:*:*:*:*:*:*:*", ""), }, } @@ -256,7 +256,7 @@ func TestBothSecdbAndNvdMatches_DifferentPackageName(t *testing.T) { Type: syftPkg.ApkPkg, CPEs: []cpe.CPE{ // Note: the product name is NOT the same as the package name - cpe.Must("cpe:2.3:a:*:libvncumbrellaproject:0.9.9:*:*:*:*:*:*:*"), + cpe.Must("cpe:2.3:a:*:libvncumbrellaproject:0.9.9:*:*:*:*:*:*:*", ""), }, } @@ -330,13 +330,13 @@ func TestNvdOnlyMatches(t *testing.T) { Version: "0.9.9", Type: syftPkg.ApkPkg, CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:a:*:libvncserver:0.9.9:*:*:*:*:*:*:*"), + cpe.Must("cpe:2.3:a:*:libvncserver:0.9.9:*:*:*:*:*:*:*", ""), }, } vulnFound, err := vulnerability.NewVulnerability(nvdVuln) assert.NoError(t, err) - vulnFound.CPEs = []cpe.CPE{cpe.Must(nvdVuln.CPEs[0])} + vulnFound.CPEs = []cpe.CPE{cpe.Must(nvdVuln.CPEs[0], "")} expected := []match.Match{ { @@ -356,7 +356,7 @@ func TestNvdOnlyMatches(t *testing.T) { }, }, Found: search.CPEResult{ - CPEs: []string{vulnFound.CPEs[0].BindToFmtString()}, + CPEs: []string{vulnFound.CPEs[0].Attributes.BindToFmtString()}, VersionConstraint: vulnFound.Constraint.String(), VulnerabilityID: "CVE-2020-1", }, @@ -409,13 +409,13 @@ func TestNvdMatchesProperVersionFiltering(t *testing.T) { Version: "0.9.11-r10", Type: syftPkg.ApkPkg, CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:a:*:libvncserver:0.9.11:*:*:*:*:*:*:*"), + cpe.Must("cpe:2.3:a:*:libvncserver:0.9.11:*:*:*:*:*:*:*", ""), }, } vulnFound, err := vulnerability.NewVulnerability(nvdVulnMatch) assert.NoError(t, err) - vulnFound.CPEs = []cpe.CPE{cpe.Must(nvdVulnMatch.CPEs[0])} + vulnFound.CPEs = []cpe.CPE{cpe.Must(nvdVulnMatch.CPEs[0], "")} expected := []match.Match{ { @@ -435,7 +435,7 @@ func TestNvdMatchesProperVersionFiltering(t *testing.T) { }, }, Found: search.CPEResult{ - CPEs: []string{vulnFound.CPEs[0].BindToFmtString()}, + CPEs: []string{vulnFound.CPEs[0].Attributes.BindToFmtString()}, VersionConstraint: vulnFound.Constraint.String(), VulnerabilityID: "CVE-2020-1", }, @@ -491,7 +491,7 @@ func TestNvdMatchesWithSecDBFix(t *testing.T) { Version: "0.9.11", Type: syftPkg.ApkPkg, CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:a:*:libvncserver:0.9.9:*:*:*:*:*:*:*"), + cpe.Must("cpe:2.3:a:*:libvncserver:0.9.9:*:*:*:*:*:*:*", ""), }, } @@ -544,7 +544,7 @@ func TestNvdMatchesNoConstraintWithSecDBFix(t *testing.T) { Version: "0.9.11", Type: syftPkg.ApkPkg, CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:a:*:libvncserver:0.9.9:*:*:*:*:*:*:*"), + cpe.Must("cpe:2.3:a:*:libvncserver:0.9.9:*:*:*:*:*:*:*", ""), }, } @@ -662,8 +662,8 @@ func TestNVDMatchBySourceIndirection(t *testing.T) { Version: "1.3.2-r0", Type: syftPkg.ApkPkg, CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:a:musl-utils:musl-utils:*:*:*:*:*:*:*:*"), - cpe.Must("cpe:2.3:a:musl-utils:musl-utils:*:*:*:*:*:*:*:*"), + cpe.Must("cpe:2.3:a:musl-utils:musl-utils:*:*:*:*:*:*:*:*", ""), + cpe.Must("cpe:2.3:a:musl-utils:musl-utils:*:*:*:*:*:*:*:*", ""), }, Upstreams: []pkg.UpstreamPackage{ { @@ -674,7 +674,7 @@ func TestNVDMatchBySourceIndirection(t *testing.T) { vulnFound, err := vulnerability.NewVulnerability(nvdVuln) assert.NoError(t, err) - vulnFound.CPEs = []cpe.CPE{cpe.Must(nvdVuln.CPEs[0])} + vulnFound.CPEs = []cpe.CPE{cpe.Must(nvdVuln.CPEs[0], "")} expected := []match.Match{ { @@ -693,7 +693,7 @@ func TestNVDMatchBySourceIndirection(t *testing.T) { }, }, Found: search.CPEResult{ - CPEs: []string{vulnFound.CPEs[0].BindToFmtString()}, + CPEs: []string{vulnFound.CPEs[0].Attributes.BindToFmtString()}, VersionConstraint: vulnFound.Constraint.String(), VulnerabilityID: "CVE-2020-1", }, diff --git a/grype/matcher/golang/matcher_test.go b/grype/matcher/golang/matcher_test.go index 0019296baf1..9f17db89535 100644 --- a/grype/matcher/golang/matcher_test.go +++ b/grype/matcher/golang/matcher_test.go @@ -62,7 +62,7 @@ func TestMatcher_SearchForStdlib(t *testing.T) { Type: syftPkg.GoModulePkg, Language: syftPkg.Go, CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:a:golang:go:1.18.3:-:*:*:*:*:*:*"), + cpe.Must("cpe:2.3:a:golang:go:1.18.3:-:*:*:*:*:*:*", ""), }, Metadata: pkg.GolangBinMetadata{}, } @@ -201,7 +201,7 @@ func (mp *mockProvider) populateData() { } func (mp *mockProvider) GetByCPE(p cpe.CPE) ([]vulnerability.Vulnerability, error) { - return mp.data["nvd:cpe"][p.BindToFmtString()], nil + return mp.data["nvd:cpe"][p.Attributes.BindToFmtString()], nil } func (mp *mockProvider) GetByDistro(d *distro.Distro, p pkg.Package) ([]vulnerability.Vulnerability, error) { diff --git a/grype/pkg/golang_metadata.go b/grype/pkg/golang_metadata.go index 0a126afc094..706c9983c9d 100644 --- a/grype/pkg/golang_metadata.go +++ b/grype/pkg/golang_metadata.go @@ -1,11 +1,14 @@ package pkg +import "github.com/anchore/syft/syft/pkg" + type GolangBinMetadata struct { - BuildSettings map[string]string `json:"goBuildSettings,omitempty"` - GoCompiledVersion string `json:"goCompiledVersion"` - Architecture string `json:"architecture"` - H1Digest string `json:"h1Digest,omitempty"` - MainModule string `json:"mainModule,omitempty"` + BuildSettings pkg.KeyValues `json:"goBuildSettings,omitempty" cyclonedx:"goBuildSettings"` + GoCompiledVersion string `json:"goCompiledVersion" cyclonedx:"goCompiledVersion"` + Architecture string `json:"architecture" cyclonedx:"architecture"` + H1Digest string `json:"h1Digest,omitempty" cyclonedx:"h1Digest"` + MainModule string `json:"mainModule,omitempty" cyclonedx:"mainModule"` + GoCryptoSettings []string `json:"goCryptoSettings,omitempty" cyclonedx:"goCryptoSettings"` } type GolangModMetadata struct { diff --git a/grype/pkg/package.go b/grype/pkg/package.go index 3297f967969..5e9befa8d31 100644 --- a/grype/pkg/package.go +++ b/grype/pkg/package.go @@ -331,8 +331,10 @@ func javaDataFromPkg(p pkg.Package) (metadata *JavaMetadata) { groupID = value.PomProperties.GroupID } if value.Manifest != nil { - if n, ok := value.Manifest.Main["Name"]; ok { - name = n + for _, kv := range value.Manifest.Main { + if kv.Key == "Name" { + name = kv.Value + } } } diff --git a/grype/pkg/package_test.go b/grype/pkg/package_test.go index d43cea81563..caff6888e26 100644 --- a/grype/pkg/package_test.go +++ b/grype/pkg/package_test.go @@ -171,12 +171,18 @@ func TestNew(t *testing.T) { Metadata: syftPkg.JavaArchive{ VirtualPath: "virtual-path-info", Manifest: &syftPkg.JavaManifest{ - Main: map[string]string{ - "Name": "main-section-name-info", + Main: syftPkg.KeyValues{ + { + Key: "Name", + Value: "main-section-name-info", + }, }, - NamedSections: map[string]map[string]string{ - "named-section": { - "named-section-key": "named-section-value", + Sections: []syftPkg.KeyValues{ + { + { + Key: "named-section-key", + Value: "named-section-value", + }, }, }, }, @@ -288,14 +294,14 @@ func TestNew(t *testing.T) { name: "golang-metadata", syftPkg: syftPkg.Package{ Metadata: syftPkg.GolangBinaryBuildinfoEntry{ - BuildSettings: map[string]string{}, + BuildSettings: syftPkg.KeyValues{}, GoCompiledVersion: "1.0.0", H1Digest: "a", MainModule: "myMainModule", }, }, metadata: GolangBinMetadata{ - BuildSettings: map[string]string{}, + BuildSettings: syftPkg.KeyValues{}, GoCompiledVersion: "1.0.0", H1Digest: "a", MainModule: "myMainModule", @@ -360,19 +366,34 @@ func TestNew(t *testing.T) { }, }, { - name: "cpp conan lock metadata", + name: "cpp conan v1 lock metadata", syftPkg: syftPkg.Package{ - Metadata: syftPkg.ConanLockEntry{ + Metadata: syftPkg.ConanV1LockEntry{ Ref: "zlib/1.2.12", - Options: map[string]string{ - "fPIC": "True", - "shared": "False", + Options: syftPkg.KeyValues{ + { + Key: "fPIC", + Value: "True", + }, + { + Key: "shared", + Value: "false", + }, }, Path: "all/conanfile.py", Context: "host", }, }, }, + { + name: "cpp conan v2 lock metadata", + syftPkg: syftPkg.Package{ + Metadata: syftPkg.ConanV2LockEntry{ + Ref: "zlib/1.2.12", + PackageID: "some-id", + }, + }, + }, { name: "cocoapods cocoapods-metadata", syftPkg: syftPkg.Package{ @@ -579,6 +600,21 @@ func TestNew(t *testing.T) { }, }, }, + { + name: "python-poetry-lock-entry", + syftPkg: syftPkg.Package{ + Metadata: syftPkg.PythonPoetryLockEntry{Index: "some-index"}, + }, + }, + { + name: "yarn-lock-entry", + syftPkg: syftPkg.Package{ + Metadata: syftPkg.YarnLockEntry{ + Resolved: "some-resolution", + Integrity: "some-digest", + }, + }, + }, } // capture each observed metadata type, we should see all of them relate to what syft provides by the end of testing diff --git a/grype/pkg/provider.go b/grype/pkg/provider.go index 29a725f2d2d..41f4cf6dee7 100644 --- a/grype/pkg/provider.go +++ b/grype/pkg/provider.go @@ -17,9 +17,10 @@ func Provide(userInput string, config ProviderConfig) ([]Package, Context, *sbom packages, ctx, s, err := syftSBOMProvider(userInput, config) if !errors.Is(err, errDoesNotProvide) { if len(config.Exclusions) > 0 { - packages, err = filterPackageExclusions(packages, config.Exclusions) - if err != nil { - return nil, ctx, s, err + var exclusionsErr error + packages, exclusionsErr = filterPackageExclusions(packages, config.Exclusions) + if exclusionsErr != nil { + return nil, ctx, s, exclusionsErr } } return packages, ctx, s, err diff --git a/grype/pkg/provider_test.go b/grype/pkg/provider_test.go index 9829a5e7e65..9b913a24d97 100644 --- a/grype/pkg/provider_test.go +++ b/grype/pkg/provider_test.go @@ -16,6 +16,7 @@ func TestProviderLocationExcludes(t *testing.T) { fixture string excludes []string expected []string + wantErr assert.ErrorAssertionFunc }{ { name: "exclude everything", @@ -41,6 +42,12 @@ func TestProviderLocationExcludes(t *testing.T) { excludes: []string{}, expected: []string{"charsets", "tomcat-embed-el"}, }, + { + name: "exclusions must not hide parsing error", + fixture: "test-fixtures/bad-sbom.json", + excludes: []string{"**/some-glob/*"}, + wantErr: assert.Error, + }, } for _, test := range tests { @@ -51,7 +58,14 @@ func TestProviderLocationExcludes(t *testing.T) { SBOMOptions: syft.DefaultCreateSBOMConfig(), }, } - pkgs, _, _, _ := Provide(test.fixture, cfg) + if test.wantErr == nil { + test.wantErr = assert.NoError + } + pkgs, _, _, err := Provide(test.fixture, cfg) + test.wantErr(t, err) + if err != nil { + return + } var pkgNames []string diff --git a/grype/pkg/purl_provider.go b/grype/pkg/purl_provider.go index 36c2a4f0e96..28d48fa2192 100644 --- a/grype/pkg/purl_provider.go +++ b/grype/pkg/purl_provider.go @@ -58,7 +58,7 @@ func decodePurlFile(reader io.Reader) ([]Package, error) { if qualifier.Key == cpesQualifierKey { rawCpes := strings.Split(qualifier.Value, ",") for _, rawCpe := range rawCpes { - c, err := cpe.New(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) } diff --git a/grype/pkg/qualifier/platformcpe/qualifier.go b/grype/pkg/qualifier/platformcpe/qualifier.go index ae33868f64e..b424dd6ad4d 100644 --- a/grype/pkg/qualifier/platformcpe/qualifier.go +++ b/grype/pkg/qualifier/platformcpe/qualifier.go @@ -18,15 +18,15 @@ func New(cpe string) qualifier.Qualifier { } func isWindowsPlatformCPE(c cpe.CPE) bool { - return c.Vendor == "microsoft" && strings.HasPrefix(c.Product, "windows") + return c.Attributes.Vendor == "microsoft" && strings.HasPrefix(c.Attributes.Product, "windows") } func isUbuntuPlatformCPE(c cpe.CPE) bool { - if c.Vendor == "canonical" && c.Product == "ubuntu_linux" { + if c.Attributes.Vendor == "canonical" && c.Attributes.Product == "ubuntu_linux" { return true } - if c.Vendor == "ubuntu" { + if c.Attributes.Vendor == "ubuntu" { return true } @@ -34,11 +34,11 @@ func isUbuntuPlatformCPE(c cpe.CPE) bool { } func isDebianPlatformCPE(c cpe.CPE) bool { - return c.Vendor == "debian" && (c.Product == "debian_linux" || c.Product == "linux") + return c.Attributes.Vendor == "debian" && (c.Attributes.Product == "debian_linux" || c.Attributes.Product == "linux") } func isWordpressPlatformCPE(c cpe.CPE) bool { - return c.Vendor == "wordpress" && c.Product == "wordpress" + return c.Attributes.Vendor == "wordpress" && c.Attributes.Product == "wordpress" } func (p platformCPE) Satisfied(d *distro.Distro, _ pkg.Package) (bool, error) { @@ -46,7 +46,7 @@ func (p platformCPE) Satisfied(d *distro.Distro, _ pkg.Package) (bool, error) { return true, nil } - c, err := cpe.New(p.cpe) + c, err := cpe.New(p.cpe, "") if err != nil { return true, err diff --git a/grype/pkg/syft_sbom_provider_test.go b/grype/pkg/syft_sbom_provider_test.go index 4c216a15f74..f58423a3a53 100644 --- a/grype/pkg/syft_sbom_provider_test.go +++ b/grype/pkg/syft_sbom_provider_test.go @@ -39,7 +39,7 @@ func TestParseSyftJSON(t *testing.T) { }, Type: "apk", CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:a:alpine:alpine_baselayout:3.2.0-r6:*:*:*:*:*:*:*"), + 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{ @@ -164,8 +164,8 @@ func TestParseSyftJSON(t *testing.T) { }, Type: "dpkg", CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:a:*:fake:1.2.0:*:*:*:*:*:*:*"), - cpe.Must("cpe:2.3:a:fake:fake:1.2.0:*:*:*:*:*:*:*"), + 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{ @@ -190,8 +190,8 @@ func TestParseSyftJSON(t *testing.T) { }, Type: "java-archive", 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:*:*:*:*:*:*:*"), + 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", Metadata: JavaMetadata{ @@ -292,8 +292,8 @@ var springImageTestCase = struct { Licenses: []string{}, Type: "java-archive", CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:a:charsets:charsets:*:*:*:*:*:java:*:*"), - cpe.Must("cpe:2.3:a:charsets:charsets:*:*:*:*:*:maven:*:*"), + cpe.Must("cpe:2.3:a:charsets:charsets:*:*:*:*:*:java:*:*", ""), + cpe.Must("cpe:2.3:a:charsets:charsets:*:*:*:*:*:maven:*:*", ""), }, PURL: "", Metadata: JavaMetadata{VirtualPath: "/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/charsets.jar"}, @@ -311,8 +311,8 @@ var springImageTestCase = struct { Licenses: []string{}, Type: "java-archive", 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:*:*"), + 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: "", Metadata: JavaMetadata{VirtualPath: "/app/libs/tomcat-embed-el-9.0.27.jar"}, diff --git a/grype/pkg/test-fixtures/bad-sbom.json b/grype/pkg/test-fixtures/bad-sbom.json new file mode 100644 index 00000000000..0967ef424bc --- /dev/null +++ b/grype/pkg/test-fixtures/bad-sbom.json @@ -0,0 +1 @@ +{} diff --git a/grype/pkg/upstream_package.go b/grype/pkg/upstream_package.go index 15d5b7d4991..73326cda1ac 100644 --- a/grype/pkg/upstream_package.go +++ b/grype/pkg/upstream_package.go @@ -32,10 +32,10 @@ func UpstreamPackages(p Package) (pkgs []Package) { cpeStrings := strset.New() for _, c := range tmp.CPEs { if u.Version != "" { - c.Version = u.Version + c.Attributes.Version = u.Version } - updatedCPEString := strings.ReplaceAll(c.BindToFmtString(), p.Name, u.Name) + updatedCPEString := strings.ReplaceAll(c.Attributes.BindToFmtString(), p.Name, u.Name) cpeStrings.Add(updatedCPEString) } @@ -43,7 +43,7 @@ func UpstreamPackages(p Package) (pkgs []Package) { // with each entry in set, convert string to CPE and update the new CPEs var updatedCPEs []cpe.CPE for _, cpeString := range cpeStrings.List() { - updatedCPE, _ := cpe.New(cpeString) + updatedCPE, _ := cpe.New(cpeString, "") updatedCPEs = append(updatedCPEs, updatedCPE) } tmp.CPEs = updatedCPEs diff --git a/grype/pkg/upstream_package_test.go b/grype/pkg/upstream_package_test.go index bf059e79059..5155ff18366 100644 --- a/grype/pkg/upstream_package_test.go +++ b/grype/pkg/upstream_package_test.go @@ -28,7 +28,7 @@ func TestUpstreamPackages(t *testing.T) { Name: "name", Version: "version", CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:*:name:name:version:*:*:*:*:*:*:*"), + cpe.Must("cpe:2.3:*:name:name:version:*:*:*:*:*:*:*", ""), }, Upstreams: []UpstreamPackage{ { @@ -42,7 +42,7 @@ func TestUpstreamPackages(t *testing.T) { Version: "version", // original CPEs: []cpe.CPE{ // name and vendor replaced - cpe.Must("cpe:2.3:*:new-name:new-name:version:*:*:*:*:*:*:*"), + cpe.Must("cpe:2.3:*:new-name:new-name:version:*:*:*:*:*:*:*", ""), }, // no upstreams }, @@ -54,7 +54,7 @@ func TestUpstreamPackages(t *testing.T) { Name: "name", Version: "version", CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:*:name:name:version:*:*:*:*:*:*:*"), + cpe.Must("cpe:2.3:*:name:name:version:*:*:*:*:*:*:*", ""), }, Upstreams: []UpstreamPackage{ { @@ -69,7 +69,7 @@ func TestUpstreamPackages(t *testing.T) { Version: "new-version", // new CPEs: []cpe.CPE{ // name, vendor, and version replaced - cpe.Must("cpe:2.3:*:new-name:new-name:new-version:*:*:*:*:*:*:*"), + cpe.Must("cpe:2.3:*:new-name:new-name:new-version:*:*:*:*:*:*:*", ""), }, // no upstreams }, @@ -81,7 +81,7 @@ func TestUpstreamPackages(t *testing.T) { Name: "name", Version: "version", CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:*:name:name:version:*:*:*:*:*:*:*"), + cpe.Must("cpe:2.3:*:name:name:version:*:*:*:*:*:*:*", ""), }, Upstreams: []UpstreamPackage{ { diff --git a/grype/presenter/internal/test_helpers.go b/grype/presenter/internal/test_helpers.go index d3f72817853..820f49634dd 100644 --- a/grype/presenter/internal/test_helpers.go +++ b/grype/presenter/internal/test_helpers.go @@ -230,11 +230,13 @@ func generatePackages(t *testing.T) []syftPkg.Package { Locations: file.NewLocationSet(file.NewVirtualLocation("/foo/bar/somefile-1.txt", "somefile-1.txt")), CPEs: []cpe.CPE{ { - Part: "a", - Vendor: "anchore", - Product: "engine", - Version: "0.9.2", - Language: "python", + Attributes: cpe.Attributes{ + Part: "a", + Vendor: "anchore", + Product: "engine", + Version: "0.9.2", + Language: "python", + }, }, }, Metadata: syftPkg.RpmDBEntry{ @@ -249,11 +251,13 @@ func generatePackages(t *testing.T) []syftPkg.Package { Locations: file.NewLocationSet(file.NewVirtualLocation("/foo/bar/somefile-2.txt", "somefile-2.txt")), CPEs: []cpe.CPE{ { - Part: "a", - Vendor: "anchore", - Product: "engine", - Version: "2.2.2", - Language: "python", + Attributes: cpe.Attributes{ + Part: "a", + Vendor: "anchore", + Product: "engine", + Version: "2.2.2", + Language: "python", + }, }, }, Licenses: syftPkg.NewLicenseSet( diff --git a/grype/presenter/models/package.go b/grype/presenter/models/package.go index d890f8db6a1..235622cd08c 100644 --- a/grype/presenter/models/package.go +++ b/grype/presenter/models/package.go @@ -31,7 +31,7 @@ type UpstreamPackage struct { func newPackage(p pkg.Package) Package { var cpes = make([]string, 0) for _, c := range p.CPEs { - cpes = append(cpes, c.BindToFmtString()) + cpes = append(cpes, c.Attributes.BindToFmtString()) } licenses := p.Licenses diff --git a/grype/search/cpe.go b/grype/search/cpe.go index d9d97dd0b6a..fa020739b15 100644 --- a/grype/search/cpe.go +++ b/grype/search/cpe.go @@ -88,7 +88,7 @@ func ByPackageCPE(store vulnerability.ProviderByCPE, d *distro.Distro, p pkg.Pac matchesByFingerprint := make(map[match.Fingerprint]match.Match) for _, c := range p.CPEs { // prefer the CPE version, but if npt specified use the package version - searchVersion := c.Version + searchVersion := c.Attributes.Version if p.Type == syftPkg.ApkPkg { searchVersion = alpineCPEComparableVersion(searchVersion) @@ -151,7 +151,7 @@ func addNewMatch(matchesByFingerprint map[match.Fingerprint]match.Match, vuln vu SearchedBy: CPEParameters{ Namespace: vuln.Namespace, CPEs: []string{ - searchedByCPE.BindToFmtString(), + searchedByCPE.Attributes.BindToFmtString(), }, Package: CPEPackageParameter{ Name: p.Name, @@ -210,12 +210,12 @@ func addMatchDetails(existingDetails []match.Detail, newDetails match.Detail) [] func filterCPEsByVersion(pkgVersion version.Version, allCPEs []cpe.CPE) (matchedCPEs []cpe.CPE) { for _, c := range allCPEs { - if c.Version == wfn.Any || c.Version == wfn.NA { + if c.Attributes.Version == wfn.Any || c.Attributes.Version == wfn.NA { matchedCPEs = append(matchedCPEs, c) continue } - constraint, err := version.GetConstraint(c.Version, version.UnknownFormat) + constraint, err := version.GetConstraint(c.Attributes.Version, version.UnknownFormat) if err != nil { // if we can't get a version constraint, don't filter out the CPE matchedCPEs = append(matchedCPEs, c) @@ -244,7 +244,7 @@ func toMatches(matchesByFingerprint map[match.Fingerprint]match.Match) (matches func cpesToString(cpes []cpe.CPE) []string { var strs = make([]string, len(cpes)) for idx, c := range cpes { - strs[idx] = c.BindToFmtString() + strs[idx] = c.Attributes.BindToFmtString() } sort.Strings(strs) return strs diff --git a/grype/search/cpe_test.go b/grype/search/cpe_test.go index 9d3f82f7c17..82cbbc0733e 100644 --- a/grype/search/cpe_test.go +++ b/grype/search/cpe_test.go @@ -166,8 +166,8 @@ func TestFindMatchesByPackageCPE(t *testing.T) { name: "match from range", p: pkg.Package{ 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:*:*"), + 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", @@ -182,8 +182,8 @@ func TestFindMatchesByPackageCPE(t *testing.T) { }, Package: pkg.Package{ 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:*:*"), + 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", @@ -217,8 +217,8 @@ func TestFindMatchesByPackageCPE(t *testing.T) { name: "multiple matches", p: pkg.Package{ 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:*:*"), + 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", @@ -233,8 +233,8 @@ func TestFindMatchesByPackageCPE(t *testing.T) { }, Package: pkg.Package{ 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:*:*"), + 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", @@ -272,8 +272,8 @@ func TestFindMatchesByPackageCPE(t *testing.T) { }, Package: pkg.Package{ 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:*:*"), + 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", @@ -308,7 +308,7 @@ func TestFindMatchesByPackageCPE(t *testing.T) { name: "exact match", p: pkg.Package{ CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:*:*:activerecord:4.0.1:*:*:*:*:*:*:*"), + cpe.Must("cpe:2.3:*:*:activerecord:4.0.1:*:*:*:*:*:*:*", ""), }, Name: "activerecord", Version: "4.0.1", @@ -323,7 +323,7 @@ func TestFindMatchesByPackageCPE(t *testing.T) { }, Package: pkg.Package{ CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:*:*:activerecord:4.0.1:*:*:*:*:*:*:*"), + cpe.Must("cpe:2.3:*:*:activerecord:4.0.1:*:*:*:*:*:*:*", ""), }, Name: "activerecord", Version: "4.0.1", @@ -368,7 +368,7 @@ func TestFindMatchesByPackageCPE(t *testing.T) { name: "fuzzy version match", p: pkg.Package{ CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:*:awesome:awesome:98SE1:rando1:*:ra:*:dunno:*:*"), + cpe.Must("cpe:2.3:*:awesome:awesome:98SE1:rando1:*:ra:*:dunno:*:*", ""), }, Name: "awesome", Version: "98SE1", @@ -381,7 +381,7 @@ func TestFindMatchesByPackageCPE(t *testing.T) { }, Package: pkg.Package{ CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:*:awesome:awesome:98SE1:rando1:*:ra:*:dunno:*:*"), + cpe.Must("cpe:2.3:*:awesome:awesome:98SE1:rando1:*:ra:*:dunno:*:*", ""), }, Name: "awesome", Version: "98SE1", @@ -414,7 +414,7 @@ func TestFindMatchesByPackageCPE(t *testing.T) { name: "multiple matched CPEs", p: pkg.Package{ CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:*:multiple:multiple:1.0:*:*:*:*:*:*:*"), + cpe.Must("cpe:2.3:*:multiple:multiple:1.0:*:*:*:*:*:*:*", ""), }, Name: "multiple", Version: "1.0", @@ -429,7 +429,7 @@ func TestFindMatchesByPackageCPE(t *testing.T) { }, Package: pkg.Package{ CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:*:multiple:multiple:1.0:*:*:*:*:*:*:*"), + cpe.Must("cpe:2.3:*:multiple:multiple:1.0:*:*:*:*:*:*:*", ""), }, Name: "multiple", Version: "1.0", @@ -467,7 +467,7 @@ func TestFindMatchesByPackageCPE(t *testing.T) { name: "filtered out match due to target_sw mismatch", p: pkg.Package{ CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:*:funfun:funfun:*:*:*:*:*:*:*:*"), + cpe.Must("cpe:2.3:*:funfun:funfun:*:*:*:*:*:*:*:*", ""), }, Name: "funfun", Version: "5.2.1", @@ -480,7 +480,7 @@ func TestFindMatchesByPackageCPE(t *testing.T) { name: "target_sw mismatch with unsupported target_sw", p: pkg.Package{ CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:*:sw:sw:*:*:*:*:*:*:*:*"), + cpe.Must("cpe:2.3:*:sw:sw:*:*:*:*:*:*:*:*", ""), }, Name: "sw", Version: "0.1", @@ -494,7 +494,7 @@ func TestFindMatchesByPackageCPE(t *testing.T) { }, Package: pkg.Package{ CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:*:sw:sw:*:*:*:*:*:*:*:*"), + cpe.Must("cpe:2.3:*:sw:sw:*:*:*:*:*:*:*:*", ""), }, Name: "sw", Version: "0.1", @@ -530,10 +530,10 @@ func TestFindMatchesByPackageCPE(t *testing.T) { name: "match included even though multiple cpes are mismatch", p: pkg.Package{ 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:*:*"), + 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", @@ -547,10 +547,10 @@ func TestFindMatchesByPackageCPE(t *testing.T) { }, Package: pkg.Package{ 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:*:*"), + 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", @@ -587,7 +587,7 @@ func TestFindMatchesByPackageCPE(t *testing.T) { name: "Ensure target_sw mismatch does not apply to java packages", p: pkg.Package{ CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:a:handlebarsjs:handlebars:*:*:*:*:*:*:*:*"), + cpe.Must("cpe:2.3:a:handlebarsjs:handlebars:*:*:*:*:*:*:*:*", ""), }, Name: "handlebars", Version: "0.1", @@ -601,7 +601,7 @@ func TestFindMatchesByPackageCPE(t *testing.T) { }, Package: pkg.Package{ CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:a:handlebarsjs:handlebars:*:*:*:*:*:*:*:*"), + cpe.Must("cpe:2.3:a:handlebarsjs:handlebars:*:*:*:*:*:*:*:*", ""), }, Name: "handlebars", Version: "0.1", @@ -637,7 +637,7 @@ func TestFindMatchesByPackageCPE(t *testing.T) { name: "Ensure target_sw mismatch does not apply to java jenkins plugins packages", p: pkg.Package{ CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:a:handlebarsjs:handlebars:*:*:*:*:*:*:*:*"), + cpe.Must("cpe:2.3:a:handlebarsjs:handlebars:*:*:*:*:*:*:*:*", ""), }, Name: "handlebars", Version: "0.1", @@ -651,7 +651,7 @@ func TestFindMatchesByPackageCPE(t *testing.T) { }, Package: pkg.Package{ CPEs: []cpe.CPE{ - cpe.Must("cpe:2.3:a:handlebarsjs:handlebars:*:*:*:*:*:*:*:*"), + cpe.Must("cpe:2.3:a:handlebarsjs:handlebars:*:*:*:*:*:*:*:*", ""), }, Name: "handlebars", Version: "0.1", @@ -728,7 +728,7 @@ func TestFilterCPEsByVersion(t *testing.T) { // format strings to CPE objects... vulnerabilityCPEs := make([]cpe.CPE, len(test.vulnerabilityCPEs)) for idx, c := range test.vulnerabilityCPEs { - vulnerabilityCPEs[idx] = cpe.Must(c) + vulnerabilityCPEs[idx] = cpe.Must(c, "") } versionObj, err := version.NewVersion(test.version, version.UnknownFormat) @@ -742,7 +742,7 @@ func TestFilterCPEsByVersion(t *testing.T) { // format CPE objects to string... actualStrs := make([]string, len(actual)) for idx, a := range actual { - actualStrs[idx] = a.BindToFmtString() + actualStrs[idx] = a.Attributes.BindToFmtString() } assert.ElementsMatch(t, test.expected, actualStrs) diff --git a/grype/search/only_vulnerable_targets.go b/grype/search/only_vulnerable_targets.go index 52dd12d6341..8064e44e9e0 100644 --- a/grype/search/only_vulnerable_targets.go +++ b/grype/search/only_vulnerable_targets.go @@ -55,7 +55,7 @@ func onlyVulnerableTargets(p pkg.Package, allVulns []vulnerability.Vulnerability for _, vuln := range allVulns { isPackageVulnerable := len(vuln.CPEs) == 0 for _, cpe := range vuln.CPEs { - targetSW := cpe.TargetSW + targetSW := cpe.Attributes.TargetSW mismatchWithUnknownLanguage := targetSW != string(p.Language) && isUnknownTarget(targetSW) if targetSW == wfn.Any || targetSW == wfn.NA || targetSW == string(p.Language) || mismatchWithUnknownLanguage { isPackageVulnerable = true diff --git a/grype/vulnerability_matcher_test.go b/grype/vulnerability_matcher_test.go index b201ade43b2..0dd380aa2a2 100644 --- a/grype/vulnerability_matcher_test.go +++ b/grype/vulnerability_matcher_test.go @@ -305,7 +305,7 @@ func TestVulnerabilityMatcher_FindMatches(t *testing.T) { } mustCPE := func(c string) cpe.CPE { - cp, err := cpe.New(c) + cp, err := cpe.New(c, "") if err != nil { t.Fatal(err) } diff --git a/test/integration/compare_sbom_input_vs_lib_test.go b/test/integration/compare_sbom_input_vs_lib_test.go index 9eacea05fbc..b65b8eb5236 100644 --- a/test/integration/compare_sbom_input_vs_lib_test.go +++ b/test/integration/compare_sbom_input_vs_lib_test.go @@ -82,6 +82,7 @@ func TestCompareSBOMInputToLibResults(t *testing.T) { string(syftPkg.SwiftPkg), string(syftPkg.GithubActionPkg), string(syftPkg.GithubActionWorkflowPkg), + string(syftPkg.ErlangOTPPkg), ) observedPkgTypes := strset.New() testCases := []struct { diff --git a/test/integration/match_by_image_test.go b/test/integration/match_by_image_test.go index 7d42d56bc10..38f75a6c65d 100644 --- a/test/integration/match_by_image_test.go +++ b/test/integration/match_by_image_test.go @@ -779,10 +779,12 @@ func testIgnoredMatches() []match.IgnoredMatch { Type: "apk", CPEs: []cpe.CPE{ { - Part: "a", - Vendor: "libvncserver", - Product: "libvncserver", - Version: "0.9.9", + Attributes: cpe.Attributes{ + Part: "a", + Vendor: "libvncserver", + Product: "libvncserver", + Version: "0.9.9", + }, }, }, PURL: "pkg:apk/alpine/libvncserver@0.9.9?arch=x86_64&distro=alpine-3.12.0",