Projects STRLCPY grype Commits d34b2819
🤬
  • feat: package qualifier for platform CPE (#1291)

    This allows filtering vulnerability matches that are only applicable
    when running on specific platforms.  It currently supports filtering
    matches that are only applicable for windows, debian, and ubuntu when
    the underlying distro is known and does not match.
    
    Additionally, wordpress platform matches are always filtered since
    wordpress plugins are not currently discoverable by syft and can be
    a significant source of false-positive matches.  These are already
    filtered when the target software component of the CPE is used
    rather than a running on platform CPE configuration.
    
    Signed-off-by: Weston Steimel <[email protected]>
  • Loading...
  • Weston Steimel committed with GitHub 11 months ago
    d34b2819
    1 parent e1bdbc7d
Revision indexing in progress... (symbol navigation in revisions will be accurate after indexed)
  • ■ ■ ■ ■ ■ ■
    grype/db/v5/pkg/qualifier/from_json.go
    skipped 4 lines
    5 5   
    6 6   "github.com/mitchellh/mapstructure"
    7 7   
     8 + "github.com/anchore/grype/grype/db/v5/pkg/qualifier/platformcpe"
    8 9   "github.com/anchore/grype/grype/db/v5/pkg/qualifier/rpmmodularity"
    9 10   "github.com/anchore/grype/internal/log"
    10 11  )
    skipped 20 lines
    31 32   var q rpmmodularity.Qualifier
    32 33   if err := mapstructure.Decode(r, &q); err != nil {
    33 34   log.Warn("Error decoding rpm-modularity package qualifier: (%v)", err)
     35 + continue
     36 + }
     37 + qualifiers = append(qualifiers, q)
     38 + case "platform-cpe":
     39 + var q platformcpe.Qualifier
     40 + if err := mapstructure.Decode(r, &q); err != nil {
     41 + log.Warn("Error decoding platform-cpe package qualifier: (%v)", err)
    34 42   continue
    35 43   }
    36 44   qualifiers = append(qualifiers, q)
    skipped 9 lines
  • ■ ■ ■ ■ ■ ■
    grype/db/v5/pkg/qualifier/platformcpe/qualifier.go
     1 +package platformcpe
     2 + 
     3 +import (
     4 + "fmt"
     5 + 
     6 + "github.com/anchore/grype/grype/pkg/qualifier"
     7 + "github.com/anchore/grype/grype/pkg/qualifier/platformcpe"
     8 +)
     9 + 
     10 +type Qualifier struct {
     11 + Kind string `json:"kind" mapstructure:"kind"` // Kind of qualifier
     12 + CPE string `json:"cpe,omitempty" mapstructure:"cpe,omitempty"` // CPE
     13 +}
     14 + 
     15 +func (q Qualifier) Parse() qualifier.Qualifier {
     16 + return platformcpe.New(q.CPE)
     17 +}
     18 + 
     19 +func (q Qualifier) String() string {
     20 + return fmt.Sprintf("kind: %s, cpe: %q", q.Kind, q.CPE)
     21 +}
     22 + 
  • ■ ■ ■ ■ ■ ■
    grype/db/v5/store/model/vulnerability_test.go
    skipped 5 lines
    6 6   "github.com/stretchr/testify/assert"
    7 7   
    8 8   "github.com/anchore/grype/grype/db/internal/sqlite"
    9  - v4 "github.com/anchore/grype/grype/db/v5"
     9 + v5 "github.com/anchore/grype/grype/db/v5"
    10 10   "github.com/anchore/grype/grype/db/v5/pkg/qualifier"
     11 + "github.com/anchore/grype/grype/db/v5/pkg/qualifier/platformcpe"
    11 12   "github.com/anchore/grype/grype/db/v5/pkg/qualifier/rpmmodularity"
    12 13  )
    13 14   
    skipped 1 lines
    15 16   tests := []struct {
    16 17   name string
    17 18   record *VulnerabilityModel
    18  - result v4.Vulnerability
     19 + result v5.Vulnerability
    19 20   }{
    20 21   {
    21 22   name: "nil package_qualifiers",
    skipped 2 lines
    24 25   ID: "CVE-12345",
    25 26   PackageQualifiers: sqlite.ToNullString(nil),
    26 27   },
    27  - result: v4.Vulnerability{
     28 + result: v5.Vulnerability{
    28 29   ID: "CVE-12345",
    29 30   },
    30 31   },
    skipped 4 lines
    35 36   ID: "CVE-919",
    36 37   PackageQualifiers: sqlite.NewNullString(`[]`, true),
    37 38   },
    38  - result: v4.Vulnerability{
     39 + result: v5.Vulnerability{
    39 40   ID: "CVE-919",
    40 41   },
    41 42   },
    skipped 4 lines
    46 47   ID: "CVE-919",
    47 48   PackageQualifiers: sqlite.NewNullString(`[{"kind": "rpm-modularity"}]`, true),
    48 49   },
    49  - result: v4.Vulnerability{
     50 + result: v5.Vulnerability{
    50 51   ID: "CVE-919",
    51 52   PackageQualifiers: []qualifier.Qualifier{
    52 53   rpmmodularity.Qualifier{
    skipped 10 lines
    63 64   ID: "CVE-919",
    64 65   PackageQualifiers: sqlite.NewNullString(`[{"kind": "rpm-modularity", "module": ""}]`, true),
    65 66   },
    66  - result: v4.Vulnerability{
     67 + result: v5.Vulnerability{
    67 68   ID: "CVE-919",
    68 69   PackageQualifiers: []qualifier.Qualifier{
    69 70   rpmmodularity.Qualifier{
    skipped 10 lines
    80 81   ID: "CVE-919",
    81 82   PackageQualifiers: sqlite.NewNullString(`[{"kind": "rpm-modularity", "module": "x.y.z:2000"}]`, true),
    82 83   },
    83  - result: v4.Vulnerability{
     84 + result: v5.Vulnerability{
    84 85   ID: "CVE-919",
    85 86   PackageQualifiers: []qualifier.Qualifier{
    86 87   rpmmodularity.Qualifier{
    skipped 4 lines
    91 92   },
    92 93   },
    93 94   {
     95 + name: "Single platformcpe package qualifier with cpe specified",
     96 + record: &VulnerabilityModel{
     97 + PK: 0,
     98 + ID: "CVE-919",
     99 + PackageQualifiers: sqlite.NewNullString(`[{"kind": "platform-cpe", "cpe": "cpe:2.3:o:canonical:ubuntu_linux:19.10:*:*:*:*:*:*:*"}]`, true),
     100 + },
     101 + result: v5.Vulnerability{
     102 + ID: "CVE-919",
     103 + PackageQualifiers: []qualifier.Qualifier{
     104 + platformcpe.Qualifier{
     105 + Kind: "platform-cpe",
     106 + CPE: "cpe:2.3:o:canonical:ubuntu_linux:19.10:*:*:*:*:*:*:*",
     107 + },
     108 + },
     109 + },
     110 + },
     111 + {
    94 112   name: "Single unrecognized package qualifier",
    95 113   record: &VulnerabilityModel{
    96 114   PK: 0,
    97 115   ID: "CVE-919",
    98 116   PackageQualifiers: sqlite.NewNullString(`[{"kind": "unknown", "some-random-slice": [{"x": true}]}]`, true),
    99 117   },
    100  - result: v4.Vulnerability{
     118 + result: v5.Vulnerability{
    101 119   ID: "CVE-919",
    102 120   },
    103 121   },
    skipped 4 lines
    108 126   ID: "CVE-919",
    109 127   PackageQualifiers: sqlite.NewNullString(`[{"some-random-slice": [{"x": true}]}]`, true),
    110 128   },
    111  - result: v4.Vulnerability{
     129 + result: v5.Vulnerability{
    112 130   ID: "CVE-919",
    113 131   },
    114 132   },
    skipped 4 lines
    119 137   ID: "CVE-919",
    120 138   PackageQualifiers: sqlite.NewNullString(`[{"kind": "rpm-modularity"},{"kind": "rpm-modularity", "module": ""},{"kind": "rpm-modularity", "module": "x.y.z:2000"},{"kind": "unknown", "some-random-slice": [{"x": true}]}]`, true),
    121 139   },
    122  - result: v4.Vulnerability{
     140 + result: v5.Vulnerability{
    123 141   ID: "CVE-919",
    124 142   PackageQualifiers: []qualifier.Qualifier{
    125 143   rpmmodularity.Qualifier{
    skipped 25 lines
  • ■ ■ ■ ■
    grype/matcher/apk/matcher.go
    skipped 44 lines
    45 45   
    46 46  func (m *Matcher) cpeMatchesWithoutSecDBFixes(store vulnerability.Provider, d *distro.Distro, p pkg.Package) ([]match.Match, error) {
    47 47   // find CPE-indexed vulnerability matches specific to the given package name and version
    48  - cpeMatches, err := search.ByPackageCPE(store, p, m.Type())
     48 + cpeMatches, err := search.ByPackageCPE(store, d, p, m.Type())
    49 49   if err != nil {
    50 50   return nil, err
    51 51   }
    skipped 125 lines
  • ■ ■ ■ ■ ■ ■
    grype/matcher/java/matcher.go
    skipped 52 lines
    53 53  func (m *Matcher) Match(store vulnerability.Provider, d *distro.Distro, p pkg.Package) ([]match.Match, error) {
    54 54   var matches []match.Match
    55 55   if m.cfg.SearchMavenUpstream {
    56  - upstreamMatches, err := m.matchUpstreamMavenPackages(store, p)
     56 + upstreamMatches, err := m.matchUpstreamMavenPackages(store, d, p)
    57 57   if err != nil {
    58 58   log.Debugf("failed to match against upstream data for %s: %v", p.Name, err)
    59 59   } else {
    skipped 13 lines
    73 73   return matches, nil
    74 74  }
    75 75   
    76  -func (m *Matcher) matchUpstreamMavenPackages(store vulnerability.Provider, p pkg.Package) ([]match.Match, error) {
     76 +func (m *Matcher) matchUpstreamMavenPackages(store vulnerability.Provider, d *distro.Distro, p pkg.Package) ([]match.Match, error) {
    77 77   var matches []match.Match
    78 78   
    79 79   if metadata, ok := p.Metadata.(pkg.JavaMetadata); ok {
    80  - for _, d := range metadata.ArchiveDigests {
    81  - if d.Algorithm == "sha1" {
    82  - indirectPackage, err := m.GetMavenPackageBySha(d.Value)
     80 + for _, digest := range metadata.ArchiveDigests {
     81 + if digest.Algorithm == "sha1" {
     82 + indirectPackage, err := m.GetMavenPackageBySha(digest.Value)
    83 83   if err != nil {
    84 84   return nil, err
    85 85   }
    86  - indirectMatches, err := search.ByPackageLanguage(store, *indirectPackage, m.Type())
     86 + indirectMatches, err := search.ByPackageLanguage(store, d, *indirectPackage, m.Type())
    87 87   if err != nil {
    88 88   return nil, err
    89 89   }
    skipped 10 lines
  • ■ ■ ■ ■
    grype/matcher/java/matcher_test.go
    skipped 39 lines
    40 40   MavenSearcher: newMockSearcher(p),
    41 41   }
    42 42   store := newMockProvider()
    43  - actual, _ := matcher.matchUpstreamMavenPackages(store, p)
     43 + actual, _ := matcher.matchUpstreamMavenPackages(store, nil, p)
    44 44   
    45 45   assert.Len(t, actual, 2, "unexpected matches count")
    46 46   
    skipped 22 lines
  • ■ ■ ■ ■ ■ ■
    grype/pkg/qualifier/platformcpe/qualifier.go
     1 +package platformcpe
     2 + 
     3 +import (
     4 + "strings"
     5 + 
     6 + "github.com/anchore/grype/grype/distro"
     7 + "github.com/anchore/grype/grype/pkg"
     8 + "github.com/anchore/grype/grype/pkg/qualifier"
     9 + "github.com/anchore/syft/syft/cpe"
     10 +)
     11 + 
     12 +type platformCPE struct {
     13 + cpe string
     14 +}
     15 + 
     16 +func New(cpe string) qualifier.Qualifier {
     17 + return &platformCPE{cpe: cpe}
     18 +}
     19 + 
     20 +func isWindowsPlatformCPE(c cpe.CPE) bool {
     21 + return c.Vendor == "microsoft" && strings.HasPrefix(c.Product, "windows")
     22 +}
     23 + 
     24 +func isUbuntuPlatformCPE(c cpe.CPE) bool {
     25 + if c.Vendor == "canonical" && c.Product == "ubuntu_linux" {
     26 + return true
     27 + }
     28 + 
     29 + if c.Vendor == "ubuntu" {
     30 + return true
     31 + }
     32 + 
     33 + return false
     34 +}
     35 + 
     36 +func isDebianPlatformCPE(c cpe.CPE) bool {
     37 + return c.Vendor == "debian" && (c.Product == "debian_linux" || c.Product == "linux")
     38 +}
     39 + 
     40 +func isWordpressPlatformCPE(c cpe.CPE) bool {
     41 + return c.Vendor == "wordpress" && c.Product == "wordpress"
     42 +}
     43 + 
     44 +func (p platformCPE) Satisfied(d *distro.Distro, _ pkg.Package) (bool, error) {
     45 + if p.cpe == "" {
     46 + return true, nil
     47 + }
     48 + 
     49 + c, err := cpe.New(p.cpe)
     50 + 
     51 + if err != nil {
     52 + return true, err
     53 + }
     54 + 
     55 + // NOTE: if syft ever supports cataloging wordpress plugins there will need to be a
     56 + // package type condition check added here
     57 + if isWordpressPlatformCPE(c) {
     58 + return false, nil
     59 + }
     60 + 
     61 + // The remaining checks are on distro, so if the distro is unknown the condition should
     62 + // be considered to be satisified and avoid filtering matches
     63 + if d == nil {
     64 + return true, nil
     65 + }
     66 + 
     67 + if isWindowsPlatformCPE(c) {
     68 + return d.Type == distro.Windows, nil
     69 + }
     70 + 
     71 + if isUbuntuPlatformCPE(c) {
     72 + return d.Type == distro.Ubuntu, nil
     73 + }
     74 + 
     75 + if isDebianPlatformCPE(c) {
     76 + return d.Type == distro.Debian, nil
     77 + }
     78 + 
     79 + return true, err
     80 +}
     81 + 
  • ■ ■ ■ ■ ■ ■
    grype/pkg/qualifier/platformcpe/qualifier_test.go
     1 +package platformcpe
     2 + 
     3 +import (
     4 + "testing"
     5 + 
     6 + "github.com/stretchr/testify/assert"
     7 + 
     8 + "github.com/anchore/grype/grype/distro"
     9 + "github.com/anchore/grype/grype/pkg"
     10 + "github.com/anchore/grype/grype/pkg/qualifier"
     11 +)
     12 + 
     13 +func TestPlatformCPE_Satisfied(t *testing.T) {
     14 + tests := []struct {
     15 + name string
     16 + platformCPE qualifier.Qualifier
     17 + pkg pkg.Package
     18 + distro *distro.Distro
     19 + satisfied bool
     20 + hasError bool
     21 + }{
     22 + {
     23 + name: "no filter on nil distro",
     24 + platformCPE: New("cpe:2.3:o:microsoft:windows:-:*:*:*:*:*:*:*"),
     25 + pkg: pkg.Package{MetadataType: pkg.UnknownMetadataType},
     26 + distro: nil,
     27 + satisfied: true,
     28 + hasError: false,
     29 + },
     30 + {
     31 + name: "no filter when platform CPE is empty",
     32 + platformCPE: New(""),
     33 + pkg: pkg.Package{MetadataType: pkg.UnknownMetadataType},
     34 + distro: &distro.Distro{Type: distro.Windows},
     35 + satisfied: true,
     36 + hasError: false,
     37 + },
     38 + {
     39 + name: "no filter when platform CPE is invalid",
     40 + platformCPE: New(";;;"),
     41 + pkg: pkg.Package{MetadataType: pkg.UnknownMetadataType},
     42 + distro: &distro.Distro{Type: distro.Windows},
     43 + satisfied: true,
     44 + hasError: true,
     45 + },
     46 + // Windows
     47 + {
     48 + name: "filter windows platform vuln when distro is not windows",
     49 + platformCPE: New("cpe:2.3:o:microsoft:windows:-:*:*:*:*:*:*:*"),
     50 + pkg: pkg.Package{MetadataType: pkg.UnknownMetadataType},
     51 + distro: &distro.Distro{Type: distro.Debian},
     52 + satisfied: false,
     53 + hasError: false,
     54 + },
     55 + {
     56 + name: "filter windows server platform vuln when distro is not windows",
     57 + platformCPE: New("cpe:2.3:o:microsoft:windows_server_2022:-:*:*:*:*:*:*:*"),
     58 + pkg: pkg.Package{MetadataType: pkg.UnknownMetadataType},
     59 + distro: &distro.Distro{Type: distro.Debian},
     60 + satisfied: false,
     61 + hasError: false,
     62 + },
     63 + {
     64 + name: "no filter windows platform vuln when distro is windows",
     65 + platformCPE: New("cpe:2.3:o:microsoft:windows:-:*:*:*:*:*:*:*"),
     66 + pkg: pkg.Package{MetadataType: pkg.UnknownMetadataType},
     67 + distro: &distro.Distro{Type: distro.Windows},
     68 + satisfied: true,
     69 + hasError: false,
     70 + },
     71 + {
     72 + name: "no filter windows server platform vuln when distro is windows",
     73 + platformCPE: New("cpe:2.3:o:microsoft:windows_server_2022:-:*:*:*:*:*:*:*"),
     74 + pkg: pkg.Package{MetadataType: pkg.UnknownMetadataType},
     75 + distro: &distro.Distro{Type: distro.Windows},
     76 + satisfied: true,
     77 + hasError: false,
     78 + },
     79 + // Debian
     80 + {
     81 + name: "filter debian platform vuln when distro is not debian",
     82 + platformCPE: New("cpe:2.3:o:debian:debian_linux:-:*:*:*:*:*:*:*"),
     83 + pkg: pkg.Package{MetadataType: pkg.UnknownMetadataType},
     84 + distro: &distro.Distro{Type: distro.Ubuntu},
     85 + satisfied: false,
     86 + hasError: false,
     87 + },
     88 + {
     89 + name: "filter debian platform vuln when distro is not debian (alternate encountered cpe)",
     90 + platformCPE: New("cpe:2.3:o:debian:linux:-:*:*:*:*:*:*:*"),
     91 + pkg: pkg.Package{MetadataType: pkg.UnknownMetadataType},
     92 + distro: &distro.Distro{Type: distro.SLES},
     93 + satisfied: false,
     94 + hasError: false,
     95 + },
     96 + {
     97 + name: "no filter debian platform vuln when distro is debian",
     98 + platformCPE: New("cpe:2.3:o:debian:debian_linux:-:*:*:*:*:*:*:*"),
     99 + pkg: pkg.Package{MetadataType: pkg.UnknownMetadataType},
     100 + distro: &distro.Distro{Type: distro.Debian},
     101 + satisfied: true,
     102 + hasError: false,
     103 + },
     104 + {
     105 + name: "no filter debian platform vuln when distro is debian (alternate encountered cpe)",
     106 + platformCPE: New("cpe:2.3:o:debian:linux:-:*:*:*:*:*:*:*"),
     107 + pkg: pkg.Package{MetadataType: pkg.UnknownMetadataType},
     108 + distro: &distro.Distro{Type: distro.Debian},
     109 + satisfied: true,
     110 + hasError: false,
     111 + },
     112 + // Ubuntu
     113 + {
     114 + name: "filter ubuntu platform vuln when distro is not ubuntu",
     115 + platformCPE: New("cpe:2.3:o:canonical:ubuntu_linux:-:*:*:*:*:*:*:*"),
     116 + pkg: pkg.Package{MetadataType: pkg.UnknownMetadataType},
     117 + distro: &distro.Distro{Type: distro.SLES},
     118 + satisfied: false,
     119 + hasError: false,
     120 + },
     121 + {
     122 + name: "filter ubuntu platform vuln when distro is not ubuntu (alternate encountered cpe)",
     123 + platformCPE: New("cpe:2.3:o:ubuntu:vivid:-:*:*:*:*:*:*:*"),
     124 + pkg: pkg.Package{MetadataType: pkg.UnknownMetadataType},
     125 + distro: &distro.Distro{Type: distro.Alpine},
     126 + satisfied: false,
     127 + hasError: false,
     128 + },
     129 + {
     130 + name: "no filter ubuntu platform vuln when distro is ubuntu",
     131 + platformCPE: New("cpe:2.3:o:canonical:ubuntu_linux:-:*:*:*:*:*:*:*"),
     132 + pkg: pkg.Package{MetadataType: pkg.UnknownMetadataType},
     133 + distro: &distro.Distro{Type: distro.Ubuntu},
     134 + satisfied: true,
     135 + hasError: false,
     136 + },
     137 + {
     138 + name: "no filter ubuntu platform vuln when distro is ubuntu (alternate encountered cpe)",
     139 + platformCPE: New("cpe:2.3:o:ubuntu:vivid:-:*:*:*:*:*:*:*"),
     140 + pkg: pkg.Package{MetadataType: pkg.UnknownMetadataType},
     141 + distro: &distro.Distro{Type: distro.Ubuntu},
     142 + satisfied: true,
     143 + hasError: false,
     144 + },
     145 + // Wordpress
     146 + {
     147 + name: "always filter wordpress platform vulns (no known distro)",
     148 + platformCPE: New("cpe:2.3:o:wordpress:wordpress:-:*:*:*:*:*:*:*"),
     149 + pkg: pkg.Package{MetadataType: pkg.UnknownMetadataType},
     150 + distro: nil,
     151 + satisfied: false,
     152 + hasError: false,
     153 + },
     154 + {
     155 + name: "always filter wordpress platform vulns (known distro)",
     156 + platformCPE: New("cpe:2.3:o:ubuntu:vivid:-:*:*:*:*:*:*:*"),
     157 + pkg: pkg.Package{MetadataType: pkg.UnknownMetadataType},
     158 + distro: &distro.Distro{Type: distro.Alpine},
     159 + satisfied: false,
     160 + hasError: false,
     161 + },
     162 + }
     163 + 
     164 + for _, test := range tests {
     165 + t.Run(test.name, func(t *testing.T) {
     166 + s, err := test.platformCPE.Satisfied(test.distro, test.pkg)
     167 + 
     168 + if test.hasError {
     169 + assert.Error(t, err)
     170 + } else {
     171 + assert.NoError(t, err)
     172 + }
     173 + 
     174 + assert.Equal(t, test.satisfied, s)
     175 + })
     176 + }
     177 +}
     178 + 
  • ■ ■ ■ ■ ■ ■
    grype/pkg/qualifier/qualifier.go
    1 1  package qualifier
    2 2   
    3  -import "github.com/anchore/grype/grype/pkg"
     3 +import (
     4 + "github.com/anchore/grype/grype/distro"
     5 + "github.com/anchore/grype/grype/pkg"
     6 +)
    4 7   
    5 8  type Qualifier interface {
    6  - Satisfied(p pkg.Package) (bool, error)
     9 + Satisfied(d *distro.Distro, p pkg.Package) (bool, error)
    7 10  }
    8 11   
  • ■ ■ ■ ■ ■
    grype/pkg/qualifier/rpmmodularity/qualifier.go
    skipped 2 lines
    3 3  import (
    4 4   "strings"
    5 5   
     6 + "github.com/anchore/grype/grype/distro"
    6 7   "github.com/anchore/grype/grype/pkg"
    7 8   "github.com/anchore/grype/grype/pkg/qualifier"
    8 9  )
    skipped 6 lines
    15 16   return &rpmModularity{module: module}
    16 17  }
    17 18   
    18  -func (r rpmModularity) Satisfied(p pkg.Package) (bool, error) {
     19 +func (r rpmModularity) Satisfied(_ *distro.Distro, p pkg.Package) (bool, error) {
    19 20   if p.MetadataType == pkg.RpmMetadataType {
    20 21   // If unable to determine package modularity, the constraint should be considered satisfied
    21 22   if p.Metadata == nil {
    skipped 27 lines
  • ■ ■ ■ ■
    grype/pkg/qualifier/rpmmodularity/qualifier_test.go
    skipped 92 lines
    93 93   
    94 94   for _, test := range tests {
    95 95   t.Run(test.name, func(t *testing.T) {
    96  - s, err := test.rpmModularity.Satisfied(test.pkg)
     96 + s, err := test.rpmModularity.Satisfied(nil, test.pkg)
    97 97   assert.NoError(t, err)
    98 98   assert.Equal(t, test.satisfied, s)
    99 99   })
    skipped 3 lines
  • ■ ■ ■ ■ ■
    grype/search/cpe.go
    skipped 7 lines
    8 8   "github.com/facebookincubator/nvdtools/wfn"
    9 9   "github.com/scylladb/go-set/strset"
    10 10   
     11 + "github.com/anchore/grype/grype/distro"
    11 12   "github.com/anchore/grype/grype/match"
    12 13   "github.com/anchore/grype/grype/pkg"
    13 14   "github.com/anchore/grype/grype/version"
    skipped 61 lines
    75 76  }
    76 77   
    77 78  // ByPackageCPE retrieves all vulnerabilities that match the generated CPE
    78  -func ByPackageCPE(store vulnerability.ProviderByCPE, p pkg.Package, upstreamMatcher match.MatcherType) ([]match.Match, error) {
     79 +func ByPackageCPE(store vulnerability.ProviderByCPE, d *distro.Distro, p pkg.Package, upstreamMatcher match.MatcherType) ([]match.Match, error) {
    79 80   // we attempt to merge match details within the same matcher when searching by CPEs, in this way there are fewer duplicated match
    80 81   // objects (and fewer duplicated match details).
    81 82   matchesByFingerprint := make(map[match.Fingerprint]match.Match)
    skipped 19 lines
    101 102   return nil, fmt.Errorf("matcher failed to fetch by CPE pkg=%q: %w", p.Name, err)
    102 103   }
    103 104   
    104  - applicableVulns, err := onlyQualifiedPackages(p, allPkgVulns)
     105 + applicableVulns, err := onlyQualifiedPackages(d, p, allPkgVulns)
    105 106   if err != nil {
    106 107   return nil, fmt.Errorf("unable to filter cpe-related vulnerabilities: %w", err)
    107 108   }
    skipped 134 lines
  • ■ ■ ■ ■
    grype/search/cpe_test.go
    skipped 648 lines
    649 649   t.Run(test.name, func(t *testing.T) {
    650 650   p, err := db.NewVulnerabilityProvider(newMockStore())
    651 651   require.NoError(t, err)
    652  - actual, err := ByPackageCPE(p, test.p, matcher)
     652 + actual, err := ByPackageCPE(p, nil, test.p, matcher)
    653 653   assert.NoError(t, err)
    654 654   assertMatchesUsingIDsForVulnerabilities(t, test.expected, actual)
    655 655   for idx, e := range test.expected {
    skipped 418 lines
  • ■ ■ ■ ■ ■ ■
    grype/search/criteria.go
    skipped 23 lines
    24 24   for _, c := range criteria {
    25 25   switch c {
    26 26   case ByCPE:
    27  - m, err := ByPackageCPE(store, p, upstreamMatcher)
     27 + m, err := ByPackageCPE(store, d, p, upstreamMatcher)
    28 28   if err != nil {
    29 29   log.Warnf("could not match by package CPE (package=%+v): %v", p, err)
    30 30   continue
    31 31   }
    32 32   matches = append(matches, m...)
    33 33   case ByLanguage:
    34  - m, err := ByPackageLanguage(store, p, upstreamMatcher)
     34 + m, err := ByPackageLanguage(store, d, p, upstreamMatcher)
    35 35   if err != nil {
    36 36   log.Warnf("could not match by package language (package=%+v): %v", p, err)
    37 37   continue
    skipped 14 lines
  • ■ ■ ■ ■
    grype/search/distro.go
    skipped 24 lines
    25 25   return nil, fmt.Errorf("matcher failed to fetch distro=%q pkg=%q: %w", d, p.Name, err)
    26 26   }
    27 27   
    28  - applicableVulns, err := onlyQualifiedPackages(p, allPkgVulns)
     28 + applicableVulns, err := onlyQualifiedPackages(d, p, allPkgVulns)
    29 29   if err != nil {
    30 30   return nil, fmt.Errorf("unable to filter distro-related vulnerabilities: %w", err)
    31 31   }
    skipped 43 lines
  • ■ ■ ■ ■ ■
    grype/search/language.go
    skipped 2 lines
    3 3  import (
    4 4   "fmt"
    5 5   
     6 + "github.com/anchore/grype/grype/distro"
    6 7   "github.com/anchore/grype/grype/match"
    7 8   "github.com/anchore/grype/grype/pkg"
    8 9   "github.com/anchore/grype/grype/version"
    9 10   "github.com/anchore/grype/grype/vulnerability"
    10 11  )
    11 12   
    12  -func ByPackageLanguage(store vulnerability.ProviderByLanguage, p pkg.Package, upstreamMatcher match.MatcherType) ([]match.Match, error) {
     13 +func ByPackageLanguage(store vulnerability.ProviderByLanguage, d *distro.Distro, p pkg.Package, upstreamMatcher match.MatcherType) ([]match.Match, error) {
    13 14   verObj, err := version.NewVersionFromPkg(p)
    14 15   if err != nil {
    15 16   return nil, fmt.Errorf("matcher failed to parse version pkg=%q ver=%q: %w", p.Name, p.Version, err)
    skipped 4 lines
    20 21   return nil, fmt.Errorf("matcher failed to fetch language=%q pkg=%q: %w", p.Language, p.Name, err)
    21 22   }
    22 23   
    23  - applicableVulns, err := onlyQualifiedPackages(p, allPkgVulns)
     24 + applicableVulns, err := onlyQualifiedPackages(d, p, allPkgVulns)
    24 25   if err != nil {
    25 26   return nil, fmt.Errorf("unable to filter language-related vulnerabilities: %w", err)
    26 27   }
    skipped 34 lines
  • ■ ■ ■ ■
    grype/search/language_test.go
    skipped 120 lines
    121 121   store := newMockProviderByLanguage()
    122 122   for _, c := range cases {
    123 123   t.Run(c.p.Name, func(t *testing.T) {
    124  - actual, err := ByPackageLanguage(store, c.p, match.RubyGemMatcher)
     124 + actual, err := ByPackageLanguage(store, nil, c.p, match.RubyGemMatcher)
    125 125   assert.NoError(t, err)
    126 126   assertMatchesUsingIDsForVulnerabilities(t, expectedMatch(c.p, c.constraint), actual)
    127 127   })
    skipped 3 lines
  • ■ ■ ■ ■ ■ ■
    grype/search/only_qualified_packages.go
    skipped 2 lines
    3 3  import (
    4 4   "fmt"
    5 5   
     6 + "github.com/anchore/grype/grype/distro"
    6 7   "github.com/anchore/grype/grype/pkg"
    7 8   "github.com/anchore/grype/grype/vulnerability"
    8 9  )
    9 10   
    10  -func onlyQualifiedPackages(p pkg.Package, allVulns []vulnerability.Vulnerability) ([]vulnerability.Vulnerability, error) {
     11 +func onlyQualifiedPackages(d *distro.Distro, p pkg.Package, allVulns []vulnerability.Vulnerability) ([]vulnerability.Vulnerability, error) {
    11 12   var vulns []vulnerability.Vulnerability
    12 13   
    13 14   for _, vuln := range allVulns {
    14 15   isVulnerable := true
    15 16   
    16 17   for _, q := range vuln.PackageQualifiers {
    17  - v, err := q.Satisfied(p)
     18 + v, err := q.Satisfied(d, p)
    18 19   
    19 20   if err != nil {
    20  - return nil, fmt.Errorf("failed to check package qualifier=%q for package=%q: %w", q, p, err)
     21 + return nil, fmt.Errorf("failed to check package qualifier=%q for distro=%q package=%q: %w", q, d, p, err)
    21 22   }
    22 23   
    23 24   isVulnerable = v
    skipped 15 lines
Please wait...
Page is in error, reload to recover