8000 Refactor matcher ignore result by kzantow · Pull Request #2658 · anchore/grype · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Refactor matcher ignore result #2658

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
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
2 changes: 1 addition & 1 deletion grype/match/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type Matcher interface {

// Match is called for every package found, returning any matches and an optional Ignorer which will be applied
// after all matches are found
Match(vp vulnerability.Provider, p pkg.Package) ([]Match, []IgnoredMatch, error)
Match(vp vulnerability.Provider, p pkg.Package) ([]Match, []IgnoreFilter, error)
}

// fatalError can be returned from a Matcher to indicate the matching process should stop.
Expand Down
32 changes: 17 additions & 15 deletions grype/matcher/apk/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func (m *Matcher) Type() match.MatcherType {
return match.ApkMatcher
}

func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoredMatch, error) {
func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoreFilter, error) {
var matches []match.Match

// direct matches with package itself
Expand Down Expand Up @@ -218,7 +218,7 @@ func (m *Matcher) findMatchesForOriginPackage(store vulnerability.Provider, p pk
// we want to report these NAK entries as match.IgnoredMatch, to allow for later processing to create ignore rules
// based on packages which overlap by location, such as a python binary found in addition to the python APK entry --
// we want to NAK this vulnerability for BOTH packages
func (m *Matcher) findNaksForPackage(provider vulnerability.Provider, p pkg.Package) ([]match.IgnoredMatch, error) {
func (m *Matcher) findNaksForPackage(provider vulnerability.Provider, p pkg.Package) ([]match.IgnoreFilter, error) {
// TODO: this was only applying to specific distros as originally implemented; this should probably be removed:
if d := p.Distro; d == nil || d.Type != distro.Wolfi && d.Type != distro.Chainguard && d.Type != distro.Alpine {
return nil, nil
Expand Down Expand Up @@ -248,21 +248,23 @@ func (m *Matcher) findNaksForPackage(provider vulnerability.Provider, p pkg.Pack
naks = append(naks, upstreamNaks...)
}

var ignores []match.IgnoredMatch
meta, ok := p.Metadata.(pkg.ApkMetadata)
if !ok {
return nil, nil
}

var ignores []match.IgnoreFilter
for _, nak := range naks {
ignores = append(ignores, match.IgnoredMatch{
Match: match.Match{
Vulnerability: nak,
Package: p,
Details: nil, // Probably don't need details here
},
AppliedIgnoreRules: []match.IgnoreRule{
{
for _, f := range meta.Files {
ignores = append(ignores,
match.IgnoreRule{
Vulnerability: nak.ID,
Reason: "NAK",
},
},
})
Reason: "Explicit APK NAK",
Package: match.IgnoreRulePackage{
Location: f.Path,
},
})
}
}

return ignores, nil
Expand Down
2 changes: 1 addition & 1 deletion grype/matcher/dotnet/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ func (m *Matcher) Type() match.MatcherType {
return match.DotnetMatcher
}

func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoredMatch, error) {
func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoreFilter, error) {
return internal.MatchPackageByEcosystemAndCPEs(store, p, m.Type(), m.cfg.UseCPEs)
}
2 changes: 1 addition & 1 deletion grype/matcher/dpkg/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func (m *Matcher) Type() match.MatcherType {
return match.DpkgMatcher
}

func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoredMatch, error) {
func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoreFilter, error) {
matches := make([]match.Match, 0)

sourceMatches, err := m.matchUpstreamPackages(store, p)
Expand Down
2 changes: 1 addition & 1 deletion grype/matcher/golang/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func (m *Matcher) Type() match.MatcherType {
return match.GoModuleMatcher
}

func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoredMatch, error) {
func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoreFilter, error) {
matches := make([]match.Match, 0)

mainModule := ""
Expand Down
6 changes: 3 additions & 3 deletions grype/matcher/internal/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import (
"github.com/anchore/grype/internal/log"
)

func MatchPackageByEcosystemAndCPEs(store vulnerability.Provider, p pkg.Package, matcher match.MatcherType, includeCPEs bool) ([]match.Match, []match.IgnoredMatch, error) {
func MatchPackageByEcosystemAndCPEs(store vulnerability.Provider, p pkg.Package, matcher match.MatcherType, includeCPEs bool) ([]match.Match, []match.IgnoreFilter, error) {
var matches []match.Match
var ignored []match.IgnoredMatch
var ignored []match.IgnoreFilter

for _, name := range store.PackageSearchNames(p) {
nameMatches, nameIgnores, err := MatchPackageByEcosystemPackageNameAndCPEs(store, p, name, matcher, includeCPEs)
Expand All @@ -25,7 +25,7 @@ func MatchPackageByEcosystemAndCPEs(store vulnerability.Provider, p pkg.Package,
return matches, ignored, nil
}

func MatchPackageByEcosystemPackageNameAndCPEs(store vulnerability.Provider, p pkg.Package, packageName string, matcher match.MatcherType, includeCPEs bool) ([]match.Match, []match.IgnoredMatch, error) {
func MatchPackageByEcosystemPackageNameAndCPEs(store vulnerability.Provider, p pkg.Package, packageName string, matcher match.MatcherType, includeCPEs bool) ([]match.Match, []match.IgnoreFilter, error) {
matches, ignored, err := MatchPackageByEcosystemPackageName(store, p, packageName, matcher)
if err != nil {
log.Debugf("could not match by package ecosystem (package=%+v): %v", p, err)
Expand Down
2 changes: 1 addition & 1 deletion grype/matcher/internal/distro.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"github.com/anchore/grype/internal/log"
)

func MatchPackageByDistro(provider vulnerability.Provider, p pkg.Package, upstreamMatcher match.MatcherType) ([]match.Match, []match.IgnoredMatch, error) {
func MatchPackageByDistro(provider vulnerability.Provider, p pkg.Package, upstreamMatcher match.MatcherType) ([]match.Match, []match.IgnoreFilter, error) {
if p.Distro == nil {
return nil, nil, nil
}
Expand Down
6 changes: 3 additions & 3 deletions grype/matcher/internal/language.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import (
"github.com/anchore/grype/internal/log"
)

func MatchPackageByLanguage(store vulnerability.Provider, p pkg.Package, matcherType match.MatcherType) ([]match.Match, []match.IgnoredMatch, error) {
func MatchPackageByLanguage(store vulnerability.Provider, p pkg.Package, matcherType match.MatcherType) ([]match.Match, []match.IgnoreFilter, error) {
var matches []match.Match
var ignored []match.IgnoredMatch
var ignored []match.IgnoreFilter

for _, name := range store.PackageSearchNames(p) {
nameMatches, nameIgnores, err := MatchPackageByEcosystemPackageName(store, p, name, matcherType)
Expand All @@ -28,7 +28,7 @@ func MatchPackageByLanguage(store vulnerability.Provider, p pkg.Package, matcher
return matches, ignored, nil
}

func MatchPackageByEcosystemPackageName(provider vulnerability.Provider, p pkg.Package, packageName string, matcherType match.MatcherType) ([]match.Match, []match.IgnoredMatch, error) {
func MatchPackageByEcosystemPackageName(provider vulnerability.Provider, p pkg.Package, packageName string, matcherType match.MatcherType) ([]match.Match, []match.IgnoreFilter, error) {
if isUnknownVersion(p.Version) {
log.WithFields("package", p.Name).Trace("skipping package with unknown version")
return nil, nil, nil
Expand Down
2 changes: 1 addition & 1 deletion grype/matcher/java/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func (m *Matcher) Type() match.MatcherType {
return match.JavaMatcher
}

func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoredMatch, error) {
func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoreFilter, error) {
var matches []match.Match

if m.cfg.SearchMavenUpstream {
Expand Down
2 changes: 1 addition & 1 deletion grype/matcher/javascript/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ func (m *Matcher) Type() match.MatcherType {
return match.JavascriptMatcher
}

func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoredMatch, error) {
func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoreFilter, error) {
return internal.MatchPackageByEcosystemAndCPEs(store, p, m.Type(), m.cfg.UseCPEs)
}
4 changes: 2 additions & 2 deletions grype/matcher/mock/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (

// MatchFunc is a function that takes a vulnerability provider and a package,
// and returns matches, ignored matches, and an error.
type MatchFunc func(vp vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoredMatch, error)
type MatchFunc func(vp vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoreFilter, error)

// Matcher is a mock implementation of the match.Matcher interface. This is
// intended for testing purposes only.
Expand All @@ -36,7 +36,7 @@ func (m Matcher) Type() match.MatcherType {
return "MOCK"
}

func (m Matcher) Match(vp vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoredMatch, error) {
func (m Matcher) Match(vp vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoreFilter, error) {
if m.matchFunc != nil {
return m.matchFunc(vp, p)
}
Expand Down
2 changes: 1 addition & 1 deletion grype/matcher/msrc/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func (m *Matcher) Type() match.MatcherType {
return match.MsrcMatcher
}

func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoredMatch, error) {
func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoreFilter, error) {
// find KB matches for the MSFT version given in the package and version.
// The "distro" holds the information about the Windows version, and its
// patch (KB)
Expand Down
2 changes: 1 addition & 1 deletion grype/matcher/portage/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ func (m *Matcher) Type() match.MatcherType {
return match.PortageMatcher
}

func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoredMatch, error) {
func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoreFilter, error) {
return internal.MatchPackageByDistro(store, p, m.Type())
}
2 changes: 1 addition & 1 deletion grype/matcher/python/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ func (m *Matcher) Type() match.MatcherType {
return match.PythonMatcher
}

func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoredMatch, error) {
func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoreFilter, error) {
return internal.MatchPackageByEcosystemAndCPEs(store, p, m.Type(), m.cfg.UseCPEs)
}
2 changes: 1 addition & 1 deletion grype/matcher/rpm/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func (m *Matcher) Type() match.MatcherType {
}

//nolint:funlen
func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoredMatch, error) {
func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoreFilter, error) {
matches := make([]match.Match, 0)

// let's match with a synthetic package that doesn't exist. We will create a new
Expand Down
2 changes: 1 addition & 1 deletion grype/matcher/ruby/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ func (m *Matcher) Type() match.MatcherType {
return match.RubyGemMatcher
}

func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoredMatch, error) {
func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoreFilter, error) {
return internal.MatchPackageByEcosystemAndCPEs(store, p, m.Type(), m.cfg.UseCPEs)
}
2 changes: 1 addition & 1 deletion grype/matcher/rust/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ func (m *Matcher) Type() match.MatcherType {
return match.RustMatcher
}

func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoredMatch, error) {
func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoreFilter, error) {
return internal.MatchPackageByEcosystemAndCPEs(store, p, m.Type(), m.cfg.UseCPEs)
}
2 changes: 1 addition & 1 deletion grype/matcher/stock/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ func (m *Matcher) Type() match.MatcherType {
return match.StockMatcher
}

func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoredMatch, error) {
func (m *Matcher) Match(store vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoreFilter, error) {
return internal.MatchPackageByEcosystemAndCPEs(store, p, m.Type(), m.cfg.UseCPEs)
}
31 changes: 18 additions & 13 deletions grype/vulnerability_matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ func (m *VulnerabilityMatcher) searchDBForMatches(
progressMonitor *monitorWriter,
) (match.Matches, error) {
var allMatches []match.Match
var allIgnored []match.IgnoredMatch
var allIgnorers []match.IgnoreFilter
matcherIndex, defaultMatcher := newMatcherIndex(m.Matchers)

if defaultMatcher == nil {
Expand All @@ -166,7 +166,7 @@ func (m *VulnerabilityMatcher) searchDBForMatches(
matchAgainst = []match.Matcher{defaultMatcher}
}
for _, theMatcher := range matchAgainst {
matches, ignoredMatches, err := callMatcherSafely(theMatcher, m.VulnerabilityProvider, p)
matches, ignorers, err := callMatcherSafely(theMatcher, m.VulnerabilityProvider, p)
if err != nil {
if match.IsFatalError(err) {
return match.Matches{}, err
Expand All @@ -176,7 +176,7 @@ func (m *VulnerabilityMatcher) searchDBForMatches(
matcherErrs = append(matcherErrs, err)
}

allIgnored = append(allIgnored, ignoredMatches...)
allIgnorers = append(allIgnorers, ignorers...)

// Filter out matches based on records in the database exclusion table and hard-coded rules
filtered, dropped := match.ApplyExplicitIgnoreRules(m.ExclusionProvider, match.NewMatches(matches...))
Expand All @@ -198,7 +198,7 @@ func (m *VulnerabilityMatcher) searchDBForMatches(
}

// apply ignores based on matchers returning ignore rules
filtered, dropped := match.ApplyIgnoreFilters(allMatches, ignoredMatchFilter(allIgnored))
filtered, dropped := match.ApplyIgnoreFilters(allMatches, ignoredMatchFilter(allIgnorers))
logIgnoredMatches(dropped)

// get deduplicated set of matches
Expand All @@ -210,7 +210,7 @@ func (m *VulnerabilityMatcher) searchDBForMatches(
return res, errors.Join(matcherErrs...)
}

func callMatcherSafely(m match.Matcher, vp vulnerability.Provider, p pkg.Package) (matches []match.Match, ignoredMatches []match.IgnoredMatch, err error) {
func callMatcherSafely(m match.Matcher, vp vulnerability.Provider, p pkg.Package) (matches []match.Match, ignoredMatches []match.IgnoreFilter, err error) {
// handle individual matcher panics
defer func() {
if e := recover(); e != nil {
Expand Down Expand Up @@ -314,6 +314,7 @@ func (m *VulnerabilityMatcher) normalizeByCVE(match match.Match) match.Match {
// ignoreRulesByLocation implements match.IgnoreFilter to filter each matching
// package that overlaps by location and have the same vulnerability ID (CVE)
type ignoreRulesByLocation struct {
remainingFilters []match.IgnoreFilter
locationToIgnoreRules map[string][]match.IgnoreRule
}

Expand All @@ -333,18 +334,22 @@ func (i ignoreRulesByLocation) IgnoreMatch(m match.Match) []match.IgnoreRule {
return nil
}

// ignoreMatchFilter creates an ignore filter based on the provided IgnoredMatches to filter out "the same"
// ignoredMatchFilter creates an ignore filter based on the provided IgnoredMatches to filter out "the same"
// vulnerabilities reported by other matchers based on overlapping file locations
func ignoredMatchFilter(ignores []match.IgnoredMatch) match.IgnoreFilter {
func ignoredMatchFilter(ignores []match.IgnoreFilter) match.IgnoreFilter {
out := ignoreRulesByLocation{locationToIgnoreRules: map[string][]match.IgnoreRule{}}
for _, ignore := range ignores {
// TODO should this be syftPkg.FileOwner interface or similar?
if m, ok := ignore.Package.Metadata.(pkg.ApkMetadata); ok {
for _, f := range m.Files {
out.locationToIgnoreRules[f.Path] = append(out.locationToIgnoreRules[f.Path], ignore.AppliedIgnoreRules...)
}
for i := 0; i < len(ignores); i++ {
rule, ok := ignores[i].(match.IgnoreRule)
if !ok {
continue
}
if rule.Package.Location != "" {
ignores = append(ignores[:i], ignores[i+1:]...) // this rule is handled with location lookups
i--
out.locationToIgnoreRules[rule.Package.Location] = append(out.locationToIgnoreRules[rule.Package.Location], rule)
}
}
out.remainingFilters = ignores // the remaining rules are not location-based rules
return out
}

Expand Down
Loading
Loading
0