Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,25 @@ log:
# location to write the log file (default is not to have a log file)
# same as GRYPE_LOG_FILE env var
file: ""

match:
# sets the matchers below to use cpes when trying to find
# vulnerability matches. The stock matcher is the default
# when no primary matcher can be identified
java:
using-cpes: true
python:
using-cpes: true
javascript:
using-cpes: true
ruby:
using-cpes: true
dotnet:
using-cpes: true
golang:
using-cpes: true
stock:
using-cpes: true
```

## Future plans
Expand Down
14 changes: 13 additions & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ import (
"github.com/anchore/grype/grype/grypeerr"
"github.com/anchore/grype/grype/match"
"github.com/anchore/grype/grype/matcher"
"github.com/anchore/grype/grype/matcher/dotnet"
"github.com/anchore/grype/grype/matcher/golang"
"github.com/anchore/grype/grype/matcher/javascript"
"github.com/anchore/grype/grype/matcher/python"
"github.com/anchore/grype/grype/matcher/ruby"
"github.com/anchore/grype/grype/matcher/stock"
"github.com/anchore/grype/grype/pkg"
"github.com/anchore/grype/grype/presenter"
"github.com/anchore/grype/grype/store"
Expand Down Expand Up @@ -351,7 +357,13 @@ func startWorker(userInput string, failOnSeverity *vulnerability.Severity) <-cha
applyDistroHint(packages, &context, appConfig)

matchers := matcher.NewDefaultMatchers(matcher.Config{
Java: appConfig.ExternalSources.ToJavaMatcherConfig(),
Java: appConfig.ExternalSources.ToJavaMatcherConfig(appConfig.Match.Java),
Ruby: ruby.MatcherConfig(appConfig.Match.Ruby),
Python: python.MatcherConfig(appConfig.Match.Python),
Dotnet: dotnet.MatcherConfig(appConfig.Match.Dotnet),
Javascript: javascript.MatcherConfig(appConfig.Match.Javascript),
Golang: golang.MatcherConfig(appConfig.Match.Golang),
Stock: stock.MatcherConfig(appConfig.Match.Stock),
})

allMatches := grype.FindVulnerabilitiesForPackage(*store, context.Distro, matchers, packages)
Expand Down
17 changes: 16 additions & 1 deletion grype/matcher/dotnet/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@ import (
)

type Matcher struct {
UseCPEs bool
}

type MatcherConfig struct {
UseCPEs bool
}

func NewDotnetMatcher(cfg MatcherConfig) *Matcher {
return &Matcher{
UseCPEs: cfg.UseCPEs,
}
}

func (m *Matcher) PackageTypes() []syftPkg.Type {
Expand All @@ -21,5 +32,9 @@ func (m *Matcher) Type() match.MatcherType {
}

func (m *Matcher) Match(store vulnerability.Provider, d *distro.Distro, p pkg.Package) ([]match.Match, error) {
return search.ByCriteria(store, d, p, m.Type(), search.CommonCriteria...)
criteria := search.CommonCriteria
if m.UseCPEs {
criteria = append(criteria, search.ByCPE)
}
return search.ByCriteria(store, d, p, m.Type(), criteria...)
}
17 changes: 16 additions & 1 deletion grype/matcher/golang/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,17 @@ import (
)

type Matcher struct {
UseCPEs bool
}

type MatcherConfig struct {
UseCPEs bool
}

func NewGolangMatcher(cfg MatcherConfig) *Matcher {
return &Matcher{
UseCPEs: cfg.UseCPEs,
}
}

func (m *Matcher) PackageTypes() []syftPkg.Type {
Expand All @@ -38,5 +49,9 @@ func (m *Matcher) Match(store vulnerability.Provider, d *distro.Distro, p pkg.Pa
return matches, nil
}

return search.ByCriteria(store, d, p, m.Type(), search.CommonCriteria...)
criteria := search.CommonCriteria
if m.UseCPEs {
criteria = append(criteria, search.ByCPE)
}
return search.ByCriteria(store, d, p, m.Type(), criteria...)
}
9 changes: 8 additions & 1 deletion grype/matcher/java/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const (
type Matcher struct {
SearchMavenUpstream bool
MavenSearcher
UseCPEs bool
}

// MavenSearcher is the interface that wraps the GetMavenPackageBySha method.
Expand Down Expand Up @@ -104,6 +105,7 @@ func (ms *mavenSearch) GetMavenPackageBySha(sha1 string) (*pkg.Package, error) {
type MatcherConfig struct {
SearchMavenUpstream bool
MavenBaseURL string
UseCPEs bool
}

func NewJavaMatcher(cfg MatcherConfig) *Matcher {
Expand All @@ -113,6 +115,7 @@ func NewJavaMatcher(cfg MatcherConfig) *Matcher {
client: http.DefaultClient,
baseURL: cfg.MavenBaseURL,
},
cfg.UseCPEs,
}
}

Expand All @@ -134,7 +137,11 @@ func (m *Matcher) Match(store vulnerability.Provider, d *distro.Distro, p pkg.Pa
matches = append(matches, upstreamMatches...)
}
}
criteriaMatches, err := search.ByCriteria(store, d, p, m.Type(), search.CommonCriteria...)
criteria := search.CommonCriteria
if m.UseCPEs {
criteria = append(criteria, search.ByCPE)
}
criteriaMatches, err := search.ByCriteria(store, d, p, m.Type(), criteria...)
if err != nil {
return nil, fmt.Errorf("failed to match by exact package: %w", err)
}
Expand Down
17 changes: 16 additions & 1 deletion grype/matcher/javascript/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@ import (
)

type Matcher struct {
UseCPEs bool
}

type MatcherConfig struct {
UseCPEs bool
}

func NewJavascriptMatcher(cfg MatcherConfig) *Matcher {
return &Matcher{
UseCPEs: cfg.UseCPEs,
}
}

func (m *Matcher) PackageTypes() []syftPkg.Type {
Expand All @@ -21,5 +32,9 @@ func (m *Matcher) Type() match.MatcherType {
}

func (m *Matcher) Match(store vulnerability.Provider, d *distro.Distro, p pkg.Package) ([]match.Match, error) {
return search.ByCriteria(store, d, p, m.Type(), search.CommonCriteria...)
criteria := search.CommonCriteria
if m.UseCPEs {
criteria = append(criteria, search.ByCPE)
}
return search.ByCriteria(store, d, p, m.Type(), criteria...)
}
34 changes: 24 additions & 10 deletions grype/matcher/matchers.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,29 @@ type Monitor struct {

// Config contains values used by individual matcher structs for advanced configuration
type Config struct {
Java java.MatcherConfig
Java java.MatcherConfig
Ruby ruby.MatcherConfig
Python python.MatcherConfig
Dotnet dotnet.MatcherConfig
Javascript javascript.MatcherConfig
Golang golang.MatcherConfig
Stock stock.MatcherConfig
}

func NewDefaultMatchers(mc Config) []Matcher {
return []Matcher{
&dpkg.Matcher{},
&ruby.Matcher{},
&python.Matcher{},
&dotnet.Matcher{},
ruby.NewRubyMatcher(mc.Ruby),
python.NewPythonMatcher(mc.Python),
dotnet.NewDotnetMatcher(mc.Dotnet),
&rpmdb.Matcher{},
java.NewJavaMatcher(mc.Java),
&javascript.Matcher{},
javascript.NewJavascriptMatcher(mc.Javascript),
&apk.Matcher{},
&golang.Matcher{},
golang.NewGolangMatcher(mc.Golang),
&msrc.Matcher{},
&portage.Matcher{},
stock.NewStockMatcher(mc.Stock),
}
}

Expand All @@ -67,9 +74,14 @@ func trackMatcher() (*progress.Manual, *progress.Manual) {
return &packagesProcessed, &vulnerabilitiesDiscovered
}

func newMatcherIndex(matchers []Matcher) map[syftPkg.Type][]Matcher {
func newMatcherIndex(matchers []Matcher) (map[syftPkg.Type][]Matcher, Matcher) {
matcherIndex := make(map[syftPkg.Type][]Matcher)
var defaultMatcher Matcher
for _, m := range matchers {
if m.Type() == match.StockMatcher {
defaultMatcher = m
continue
}
for _, t := range m.PackageTypes() {
if _, ok := matcherIndex[t]; !ok {
matcherIndex[t] = make([]Matcher, 0)
Expand All @@ -80,7 +92,7 @@ func newMatcherIndex(matchers []Matcher) map[syftPkg.Type][]Matcher {
}
}

return matcherIndex
return matcherIndex, defaultMatcher
}

func FindMatches(store interface {
Expand All @@ -89,7 +101,7 @@ func FindMatches(store interface {
}, release *linux.Release, matchers []Matcher, packages []pkg.Package) match.Matches {
var err error
res := match.NewMatches()
matcherIndex := newMatcherIndex(matchers)
matcherIndex, defaultMatcher := newMatcherIndex(matchers)

var d *distro.Distro
if release != nil {
Expand All @@ -101,7 +113,9 @@ func FindMatches(store interface {

packagesProcessed, vulnerabilitiesDiscovered := trackMatcher()

defaultMatcher := &stock.Matcher{}
if defaultMatcher == nil {
defaultMatcher = &stock.Matcher{UseCPEs: true}
}
for _, p := range packages {
packagesProcessed.N++
log.Debugf("searching for vulnerability matches for pkg=%s", p)
Expand Down
17 changes: 16 additions & 1 deletion grype/matcher/python/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@ import (
)

type Matcher struct {
UseCPEs bool
}

type MatcherConfig struct {
UseCPEs bool
}

func NewPythonMatcher(cfg MatcherConfig) *Matcher {
return &Matcher{
UseCPEs: cfg.UseCPEs,
}
}

func (m *Matcher) PackageTypes() []syftPkg.Type {
Expand All @@ -21,5 +32,9 @@ func (m *Matcher) Type() match.MatcherType {
}

func (m *Matcher) Match(store vulnerability.Provider, d *distro.Distro, p pkg.Package) ([]match.Match, error) {
return search.ByCriteria(store, d, p, m.Type(), search.CommonCriteria...)
criteria := search.CommonCriteria
if m.UseCPEs {
criteria = append(criteria, search.ByCPE)
}
return search.ByCriteria(store, d, p, m.Type(), criteria...)
}
17 changes: 16 additions & 1 deletion grype/matcher/ruby/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@ import (
)

type Matcher struct {
UseCPEs bool
}

type MatcherConfig struct {
UseCPEs bool
}

func NewRubyMatcher(cfg MatcherConfig) *Matcher {
return &Matcher{
UseCPEs: cfg.UseCPEs,
}
}

func (m *Matcher) PackageTypes() []syftPkg.Type {
Expand All @@ -21,5 +32,9 @@ func (m *Matcher) Type() match.MatcherType {
}

func (m *Matcher) Match(store vulnerability.Provider, d *distro.Distro, p pkg.Package) ([]match.Match, error) {
return search.ByCriteria(store, d, p, m.Type(), search.CommonCriteria...)
criteria := search.CommonCriteria
if m.UseCPEs {
criteria = append(criteria, search.ByCPE)
}
return search.ByCriteria(store, d, p, m.Type(), criteria...)
}
17 changes: 16 additions & 1 deletion grype/matcher/stock/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@ import (
)

type Matcher struct {
UseCPEs bool
}

type MatcherConfig struct {
UseCPEs bool
}

func NewStockMatcher(cfg MatcherConfig) *Matcher {
return &Matcher{
UseCPEs: cfg.UseCPEs,
}
}

func (m *Matcher) PackageTypes() []syftPkg.Type {
Expand All @@ -21,5 +32,9 @@ func (m *Matcher) Type() match.MatcherType {
}

func (m *Matcher) Match(store vulnerability.Provider, d *distro.Distro, p pkg.Package) ([]match.Match, error) {
return search.ByCriteria(store, d, p, m.Type(), search.CommonCriteria...)
criteria := search.CommonCriteria
if m.UseCPEs {
criteria = append(criteria, search.ByCPE)
}
return search.ByCriteria(store, d, p, m.Type(), criteria...)
}
1 change: 0 additions & 1 deletion grype/search/criteria.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ var (
ByDistro Criteria = "by-distro"
CommonCriteria = []Criteria{
ByLanguage,
ByCPE,
}
)

Expand Down
1 change: 1 addition & 0 deletions internal/config/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ type Application struct {
Exclusions []string `yaml:"exclude" json:"exclude" mapstructure:"exclude"`
DB database `yaml:"db" json:"db" mapstructure:"db"`
ExternalSources externalSources `yaml:"external-sources" json:"externalSources" mapstructure:"external-sources"`
Match matchConfig `yaml:"match" json:"match" mapstructure:"match"`
Dev development `yaml:"dev" json:"dev" mapstructure:"dev"`
FailOn string `yaml:"fail-on-severity" json:"fail-on-severity" mapstructure:"fail-on-severity"`
FailOnSeverity *vulnerability.Severity `yaml:"-" json:"-"`
Expand Down
3 changes: 2 additions & 1 deletion internal/config/datasources.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func (cfg externalSources) loadDefaultValues(v *viper.Viper) {
v.SetDefault("external-sources.maven.base-url", defaultMavenBaseURL)
}

func (cfg externalSources) ToJavaMatcherConfig() java.MatcherConfig {
func (cfg externalSources) ToJavaMatcherConfig(matchCfg matcherConfig) java.MatcherConfig {
// always respect if global config is disabled
smu := cfg.Maven.SearchUpstreamBySha1
if !cfg.Enable {
Expand All @@ -35,5 +35,6 @@ func (cfg externalSources) ToJavaMatcherConfig() java.MatcherConfig {
return java.MatcherConfig{
SearchMavenUpstream: smu,
MavenBaseURL: cfg.Maven.BaseURL,
UseCPEs: matchCfg.UseCPEs,
}
}
Loading