Skip to content

Commit

Permalink
fix: update ignored vulnerability count in tui (#1837)
Browse files Browse the repository at this point in the history
  • Loading branch information
kzantow committed May 1, 2024
1 parent 6b9ea21 commit bd16101
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 1 deletion.
18 changes: 17 additions & 1 deletion grype/vulnerability_matcher.go
Expand Up @@ -66,6 +66,7 @@ func (m *VulnerabilityMatcher) FindMatches(pkgs []pkg.Package, context pkg.Conte
progressMonitor := trackMatcher(len(pkgs))

defer func() {
progressMonitor.Ignored.Set(int64(len(ignoredMatches)))
progressMonitor.SetCompleted()
if err != nil {
progressMonitor.MatchesDiscovered.SetError(err)
Expand Down Expand Up @@ -116,10 +117,25 @@ func (m *VulnerabilityMatcher) findDBMatches(pkgs []pkg.Package, context pkg.Con
// regresses the results (relative to the already applied ignore rules). Why do we additionally apply
// the ignore rules before normalizing? In case the user has a rule that ignores a non-normalized
// vulnerability ID, we wantMatches to ensure that the rule is honored.
originalIgnoredMatches := ignoredMatches
matches, ignoredMatches = m.applyIgnoreRules(normalizedMatches)
ignoredMatches = m.mergeIgnoredMatches(originalIgnoredMatches, ignoredMatches)
}

return &matches, ignoredMatches, err
return &matches, ignoredMatches, nil
}

func (m *VulnerabilityMatcher) mergeIgnoredMatches(allIgnoredMatches ...[]match.IgnoredMatch) []match.IgnoredMatch {
var out []match.IgnoredMatch
for _, ignoredMatches := range allIgnoredMatches {
for _, ignored := range ignoredMatches {
if m.NormalizeByCVE {
ignored.Match = m.normalizeByCVE(ignored.Match)
}
out = append(out, ignored)
}
}
return out
}

func (m *VulnerabilityMatcher) searchDBForMatches(
Expand Down
113 changes: 113 additions & 0 deletions grype/vulnerability_matcher_test.go
Expand Up @@ -8,10 +8,13 @@ import (
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/wagoodman/go-partybus"

"github.com/anchore/grype/grype/db"
grypeDB "github.com/anchore/grype/grype/db/v5"
"github.com/anchore/grype/grype/distro"
"github.com/anchore/grype/grype/event"
"github.com/anchore/grype/grype/event/monitor"
"github.com/anchore/grype/grype/grypeerr"
"github.com/anchore/grype/grype/match"
"github.com/anchore/grype/grype/matcher"
Expand All @@ -23,6 +26,7 @@ import (
"github.com/anchore/grype/grype/version"
"github.com/anchore/grype/grype/vex"
"github.com/anchore/grype/grype/vulnerability"
"github.com/anchore/grype/internal/bus"
"github.com/anchore/syft/syft/cpe"
"github.com/anchore/syft/syft/file"
"github.com/anchore/syft/syft/linux"
Expand Down Expand Up @@ -785,6 +789,48 @@ func TestVulnerabilityMatcher_FindMatches(t *testing.T) {
},
),
wantErr: nil,
wantIgnoredMatches: []match.IgnoredMatch{
{
Match: match.Match{
Vulnerability: vulnerability.Vulnerability{
Constraint: version.MustGetConstraint("< 3.7.6", version.UnknownFormat),
ID: "CVE-2014-fake-3",
Namespace: "nvd:cpe",
CPEs: []cpe.CPE{},
PackageQualifiers: []qualifier.Qualifier{},
Advisories: []vulnerability.Advisory{},
RelatedVulnerabilities: []vulnerability.Reference{
{
ID: "GHSA-2014-fake-3",
Namespace: "github:language:ruby",
},
},
},
Package: activerecordPkg,
Details: match.Details{
{
Type: match.ExactDirectMatch,
SearchedBy: map[string]any{
"language": "ruby",
"namespace": "github:language:ruby",
"package": map[string]string{"name": "activerecord", "version": "3.7.5"},
},
Found: map[string]any{
"versionConstraint": "< 3.7.6 (unknown)",
"vulnerabilityID": "GHSA-2014-fake-3",
},
Matcher: "ruby-gem-matcher",
Confidence: 1,
},
},
},
AppliedIgnoreRules: []match.IgnoreRule{
{
Vulnerability: "GHSA-2014-fake-3",
},
},
},
},
},
{
name: "normalize by cve -- ignore CVE",
Expand Down Expand Up @@ -812,6 +858,51 @@ func TestVulnerabilityMatcher_FindMatches(t *testing.T) {
},
wantMatches: match.NewMatches(),
wantIgnoredMatches: []match.IgnoredMatch{
{
Match: match.Match{
Vulnerability: vulnerability.Vulnerability{
Constraint: version.MustGetConstraint("< 3.7.6", version.UnknownFormat),
ID: "CVE-2014-fake-3",
Namespace: "nvd:cpe",
CPEs: []cpe.CPE{
mustCPE("cpe:2.3:*:activerecord:activerecord:*:*:*:*:*:rails:*:*"),
},
PackageQualifiers: []qualifier.Qualifier{},
Advisories: []vulnerability.Advisory{},
RelatedVulnerabilities: nil,
},
Package: activerecordPkg,
Details: match.Details{
{
Type: match.CPEMatch,
SearchedBy: search.CPEParameters{
Namespace: "nvd:cpe",
CPEs: []string{
"cpe:2.3:*:activerecord:activerecord:*:*:*:*:*:rails:*:*",
},
Package: search.CPEPackageParameter{
Name: "activerecord",
Version: "3.7.5",
},
},
Found: search.CPEResult{
VulnerabilityID: "CVE-2014-fake-3",
VersionConstraint: "< 3.7.6 (unknown)",
CPEs: []string{
"cpe:2.3:*:activerecord:activerecord:*:*:*:*:*:rails:*:*",
},
},
Matcher: "ruby-gem-matcher",
Confidence: 0.9,
},
},
},
AppliedIgnoreRules: []match.IgnoreRule{
{
Vulnerability: "CVE-2014-fake-3",
},
},
},
{
AppliedIgnoreRules: []match.IgnoreRule{
{
Expand Down Expand Up @@ -969,6 +1060,11 @@ func TestVulnerabilityMatcher_FindMatches(t *testing.T) {
NormalizeByCVE: tt.fields.NormalizeByCVE,
VexProcessor: tt.fields.VexProcessor,
}

listener := &busListener{}
bus.Set(listener)
defer bus.Set(nil)

actualMatches, actualIgnoreMatches, err := m.FindMatches(tt.args.pkgs, tt.args.context)
if tt.wantErr != nil {
require.ErrorIs(t, err, tt.wantErr)
Expand All @@ -992,6 +1088,9 @@ func TestVulnerabilityMatcher_FindMatches(t *testing.T) {
if d := cmp.Diff(tt.wantIgnoredMatches, actualIgnoreMatches, opts...); d != "" {
t.Errorf("FindMatches() ignored matches mismatch [ha!] (-want +got):\n%s", d)
}

// validate the bus-reported ignored counts are accurate
require.Equal(t, int64(len(tt.wantIgnoredMatches)), listener.matching.Ignored.Current())
})
}
}
Expand Down Expand Up @@ -1281,3 +1380,17 @@ func Test_filterMatchesUsingDistroFalsePositives(t *testing.T) {
})
}
}

type busListener struct {
matching monitor.Matching
}

func (b *busListener) Publish(e partybus.Event) {
if e.Type == event.VulnerabilityScanningStarted {
if m, ok := e.Value.(monitor.Matching); ok {
b.matching = m
}
}
}

var _ partybus.Publisher = (*busListener)(nil)

0 comments on commit bd16101

Please sign in to comment.