Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package grype for openSUSE:Factory checked in at 2025-03-14 23:51:46 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/grype (Old) and /work/SRC/openSUSE:Factory/.grype.new.19136 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "grype" Fri Mar 14 23:51:46 2025 rev:86 rq:1252967 version:0.89.1 Changes: -------- --- /work/SRC/openSUSE:Factory/grype/grype.changes 2025-03-07 16:48:23.737060773 +0100 +++ /work/SRC/openSUSE:Factory/.grype.new.19136/grype.changes 2025-03-14 23:52:12.568924012 +0100 @@ -1,0 +2,10 @@ +Fri Mar 14 06:27:30 UTC 2025 - opensuse_buildserv...@ojkastl.de + +- Update to version 0.89.1: + * fix: populate vulnerability.Metadata.DataSource with first + reference URL (#2523) + * fix(java): ensure fatal error from maven search bubbles up + (#2518) + * fix: exclude self from related vulnerability list (#2515) + +------------------------------------------------------------------- Old: ---- grype-0.89.0.obscpio New: ---- grype-0.89.1.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ grype.spec ++++++ --- /var/tmp/diff_new_pack.SYxvCJ/_old 2025-03-14 23:52:14.188991494 +0100 +++ /var/tmp/diff_new_pack.SYxvCJ/_new 2025-03-14 23:52:14.192991661 +0100 @@ -17,7 +17,7 @@ Name: grype -Version: 0.89.0 +Version: 0.89.1 Release: 0 Summary: A vulnerability scanner for container images and filesystems License: Apache-2.0 ++++++ _service ++++++ --- /var/tmp/diff_new_pack.SYxvCJ/_old 2025-03-14 23:52:14.224992994 +0100 +++ /var/tmp/diff_new_pack.SYxvCJ/_new 2025-03-14 23:52:14.228993160 +0100 @@ -3,7 +3,7 @@ <param name="url">https://github.com/anchore/grype</param> <param name="scm">git</param> <param name="exclude">.git</param> - <param name="revision">v0.89.0</param> + <param name="revision">v0.89.1</param> <param name="match-tag">v*</param> <param name="versionformat">@PARENT_TAG@</param> <param name="versionrewrite-pattern">v(.*)</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.SYxvCJ/_old 2025-03-14 23:52:14.248993993 +0100 +++ /var/tmp/diff_new_pack.SYxvCJ/_new 2025-03-14 23:52:14.252994160 +0100 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/anchore/grype</param> - <param name="changesrevision">1bf47c38bede40dea7b72bbe4712191820f1aa15</param></service></servicedata> + <param name="changesrevision">718ea3060267edcae7b10a9bf16c0acdad10820a</param></service></servicedata> (No newline at EOF) ++++++ grype-0.89.0.obscpio -> grype-0.89.1.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/grype-0.89.0/grype/db/v6/vulnerability.go new/grype-0.89.1/grype/db/v6/vulnerability.go --- old/grype-0.89.0/grype/db/v6/vulnerability.go 2025-03-06 17:12:29.000000000 +0100 +++ new/grype-0.89.1/grype/db/v6/vulnerability.go 2025-03-11 15:55:51.000000000 +0100 @@ -104,7 +104,7 @@ cveSet := strset.New() var relatedVulnerabilities []vulnerability.Reference for _, alias := range vuln.BlobValue.Aliases { - if cveSet.Has(alias) { + if cveSet.Has(alias) || strings.EqualFold(vuln.Name, alias) { continue } if !strings.HasPrefix(strings.ToLower(alias), "cve-") { @@ -118,7 +118,7 @@ } if affected != nil { for _, cve := range affected.CVEs { - if cveSet.Has(cve) { + if cveSet.Has(cve) || strings.EqualFold(vuln.Name, cve) { continue } if !strings.HasPrefix(strings.ToLower(cve), "cve-") { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/grype-0.89.0/grype/db/v6/vulnerability_provider.go new/grype-0.89.1/grype/db/v6/vulnerability_provider.go --- old/grype-0.89.0/grype/db/v6/vulnerability_provider.go 2025-03-06 17:12:29.000000000 +0100 +++ new/grype-0.89.1/grype/db/v6/vulnerability_provider.go 2025-03-11 15:55:51.000000000 +0100 @@ -83,20 +83,14 @@ sev, cvss, err := extractSeverities(vuln) if err != nil { log.WithFields("id", vuln.Name, "vulnerability", vuln.String()).Debug("unable to extract severity from vulnerability") - return &vulnerability.Metadata{ - ID: vuln.Name, - DataSource: strings.Split(namespace, ":")[0], - Namespace: namespace, - Severity: toSeverityString(vulnerability.UnknownSeverity), - }, nil } return &vulnerability.Metadata{ ID: vuln.Name, - DataSource: vuln.Provider.ID, + DataSource: firstReferenceURL(vuln), Namespace: namespace, Severity: toSeverityString(sev), - URLs: toURLs(vuln), + URLs: lastReferenceURLs(vuln), Description: vuln.BlobValue.Description, Cvss: cvss, KnownExploited: kevs, @@ -522,9 +516,21 @@ return strcase.ToCamel(sev.String()) } -func toURLs(vuln *VulnerabilityHandle) []string { - var out []string +// returns the first reference url to populate the DataSource +func firstReferenceURL(vuln *VulnerabilityHandle) string { for _, v := range vuln.BlobValue.References { + return v.URL + } + return "" +} + +// skip the first reference URL and return the remainder to populate the URLs +func lastReferenceURLs(vuln *VulnerabilityHandle) []string { + var out []string + for i, v := range vuln.BlobValue.References { + if i == 0 { + continue + } out = append(out, v.URL) } return out diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/grype-0.89.0/grype/db/v6/vulnerability_provider_test.go new/grype-0.89.1/grype/db/v6/vulnerability_provider_test.go --- old/grype-0.89.0/grype/db/v6/vulnerability_provider_test.go 2025-03-06 17:12:29.000000000 +0100 +++ new/grype-0.89.1/grype/db/v6/vulnerability_provider_test.go 2025-03-11 15:55:51.000000000 +0100 @@ -46,10 +46,10 @@ Advisories: []vulnerability.Advisory{}, Metadata: &vulnerability.Metadata{ ID: "CVE-2014-fake-1", - DataSource: "debian", + DataSource: "http://somewhere/CVE-2014-fake-1", Namespace: "debian:distro:debian:8", Severity: "High", - URLs: []string{"http://somewhere/CVE-2014-fake-1"}, + URLs: nil, Description: "CVE-2014-fake-1-description", }, }, @@ -65,10 +65,10 @@ Advisories: []vulnerability.Advisory{}, Metadata: &vulnerability.Metadata{ ID: "CVE-2013-fake-2", - DataSource: "debian", + DataSource: "http://somewhere/CVE-2013-fake-2", Namespace: "debian:distro:debian:8", Severity: "High", - URLs: []string{"http://somewhere/CVE-2013-fake-2"}, + URLs: nil, Description: "CVE-2013-fake-2-description", }, }, @@ -123,10 +123,10 @@ Advisories: []vulnerability.Advisory{}, Metadata: &vulnerability.Metadata{ ID: "CVE-2014-fake-4", - DataSource: "debian", + DataSource: "http://somewhere/CVE-2014-fake-4", Namespace: "nvd:cpe", Severity: "High", - URLs: []string{"http://somewhere/CVE-2014-fake-4"}, + URLs: nil, Description: "CVE-2014-fake-4-description", }, }, @@ -150,10 +150,10 @@ Advisories: []vulnerability.Advisory{}, Metadata: &vulnerability.Metadata{ ID: "CVE-2014-fake-4", - DataSource: "debian", + DataSource: "http://somewhere/CVE-2014-fake-4", Namespace: "nvd:cpe", Severity: "High", - URLs: []string{"http://somewhere/CVE-2014-fake-4"}, + URLs: nil, Description: "CVE-2014-fake-4-description", }, }, @@ -177,10 +177,10 @@ Advisories: []vulnerability.Advisory{}, Metadata: &vulnerability.Metadata{ ID: "CVE-2014-fake-3", - DataSource: "debian", + DataSource: "http://somewhere/CVE-2014-fake-3", Namespace: "nvd:cpe", Severity: "High", - URLs: []string{"http://somewhere/CVE-2014-fake-3"}, + URLs: nil, Description: "CVE-2014-fake-3-description", }, }, @@ -198,10 +198,10 @@ Advisories: []vulnerability.Advisory{}, Metadata: &vulnerability.Metadata{ ID: "CVE-2014-fake-4", - DataSource: "debian", + DataSource: "http://somewhere/CVE-2014-fake-4", Namespace: "nvd:cpe", Severity: "High", - URLs: []string{"http://somewhere/CVE-2014-fake-4"}, + URLs: nil, Description: "CVE-2014-fake-4-description", }, }, @@ -270,10 +270,10 @@ Advisories: []vulnerability.Advisory{}, Metadata: &vulnerability.Metadata{ ID: "CVE-2014-fake-1", - DataSource: "debian", + DataSource: "http://somewhere/CVE-2014-fake-1", Namespace: "debian:distro:debian:8", Severity: "High", - URLs: []string{"http://somewhere/CVE-2014-fake-1"}, + URLs: nil, Description: "CVE-2014-fake-1-description", }, }, @@ -303,6 +303,98 @@ require.Empty(t, actual) } +func Test_DataSource(t *testing.T) { + tests := []struct { + name string + vuln VulnerabilityHandle + expected vulnerability.Metadata + }{ + { + name: "no reference urls", + vuln: VulnerabilityHandle{ + BlobValue: &VulnerabilityBlob{ + References: nil, + }, + }, + expected: vulnerability.Metadata{ + DataSource: "", + URLs: nil, + }, + }, + { + name: "one reference url", + vuln: VulnerabilityHandle{ + BlobValue: &VulnerabilityBlob{ + References: []Reference{ + { + URL: "url1", + }, + }, + }, + }, + expected: vulnerability.Metadata{ + DataSource: "url1", + URLs: nil, + }, + }, + { + name: "two reference urls", + vuln: VulnerabilityHandle{ + BlobValue: &VulnerabilityBlob{ + References: []Reference{ + { + URL: "url1", + }, + { + URL: "url2", + }, + }, + }, + }, + expected: vulnerability.Metadata{ + DataSource: "url1", + URLs: []string{"url2"}, + }, + }, + { + name: "many reference urls", + vuln: VulnerabilityHandle{ + BlobValue: &VulnerabilityBlob{ + References: []Reference{ + { + URL: "url4", + }, + { + URL: "url3", + }, + { + URL: "url2", + }, + { + URL: "url1", + }, + }, + }, + }, + expected: vulnerability.Metadata{ + DataSource: "url4", + URLs: []string{"url3", "url2", "url1"}, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := newVulnerabilityMetadata(&tt.vuln, "", nil, nil) + got.Severity = "" + require.NoError(t, err) + if diff := cmp.Diff(&tt.expected, got, cmpOpts()...); diff != "" { + t.Fatal(diff) + } + }) + } +} + func cmpOpts() []cmp.Option { return []cmp.Option{ // globally ignore unexported -- these are unexported structs we cannot reference here to use cmpopts.IgnoreUnexported diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/grype-0.89.0/grype/db/v6/vulnerability_test.go new/grype-0.89.1/grype/db/v6/vulnerability_test.go --- old/grype-0.89.0/grype/db/v6/vulnerability_test.go 2025-03-06 17:12:29.000000000 +0100 +++ new/grype-0.89.1/grype/db/v6/vulnerability_test.go 2025-03-11 15:55:51.000000000 +0100 @@ -6,6 +6,9 @@ "unicode" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/anchore/grype/grype/vulnerability" ) func TestV5Namespace(t *testing.T) { @@ -467,6 +470,68 @@ }) } } + +func Test_getRelatedVulnerabilities(t *testing.T) { + tests := []struct { + name string + vuln VulnerabilityHandle + affected AffectedPackageBlob + expected []string + }{ + { + name: "GHSA with related CVEs", + vuln: VulnerabilityHandle{ + Name: "GHSA-1234", + BlobValue: &VulnerabilityBlob{ + Aliases: []string{"CVE-2024-1"}, + }, + }, + affected: AffectedPackageBlob{ + CVEs: []string{"CVE-2024-2", "CVE-2024-3"}, + }, + expected: []string{"CVE-2024-1", "CVE-2024-2", "CVE-2024-3"}, + }, + { + name: "CVE with related CVEs", + vuln: VulnerabilityHandle{ + Name: "CVE-2024-1234", + BlobValue: &VulnerabilityBlob{ + Aliases: []string{"CVE-2024-1"}, + }, + }, + affected: AffectedPackageBlob{ + CVEs: []string{"CVE-2024-2", "CVE-2024-3"}, + }, + expected: []string{"CVE-2024-1", "CVE-2024-2", "CVE-2024-3"}, + }, + { + name: "CVE with related CVEs and self", + vuln: VulnerabilityHandle{ + Name: "CVE-2024-1234", + BlobValue: &VulnerabilityBlob{ + Aliases: []string{"CVE-2024-1", "CVE-2024-1234"}, + }, + }, + affected: AffectedPackageBlob{ + CVEs: []string{"CVE-2024-2", "CVE-2024-1234"}, + }, + expected: []string{"CVE-2024-1", "CVE-2024-2"}, // does not include "CVE-2024-1234" + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := getRelatedVulnerabilities(&tt.vuln, &tt.affected) + var expected []vulnerability.Reference + for _, name := range tt.expected { + expected = append(expected, vulnerability.Reference{ + ID: name, + Namespace: v5NvdNamespace, + }) + } + require.ElementsMatch(t, expected, got) + }) + } +} func majorMinorPatch(ver string) (string, string, string) { if !unicode.IsDigit(rune(ver[0])) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/grype-0.89.0/grype/match/matcher.go new/grype-0.89.1/grype/match/matcher.go --- old/grype-0.89.0/grype/match/matcher.go 2025-03-06 17:12:29.000000000 +0100 +++ new/grype-0.89.1/grype/match/matcher.go 2025-03-11 15:55:51.000000000 +0100 @@ -1,6 +1,9 @@ package match import ( + "errors" + "fmt" + "github.com/anchore/grype/grype/pkg" "github.com/anchore/grype/grype/vulnerability" syftPkg "github.com/anchore/syft/syft/pkg" @@ -16,3 +19,26 @@ // after all matches are found Match(vp vulnerability.Provider, p pkg.Package) ([]Match, []IgnoredMatch, error) } + +// fatalError can be returned from a Matcher to indicate the matching process should stop. +// When fatalError(s) are encountered by the top-level matching process, these will be returned as errors to the caller. +type fatalError struct { + matcher MatcherType + inner error +} + +// NewFatalError creates a new fatalError wrapping the given error +func NewFatalError(matcher MatcherType, e error) error { + return fatalError{matcher: matcher, inner: e} +} + +// Error implements the error interface for fatalError. +func (f fatalError) Error() string { + return fmt.Sprintf("%s encountered a fatal error: %v", f.matcher, f.inner) +} + +// IsFatalError returns true if err includes a fatalError +func IsFatalError(err error) bool { + var fe fatalError + return err != nil && errors.As(err, &fe) +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/grype-0.89.0/grype/matcher/java/matcher.go new/grype-0.89.1/grype/matcher/java/matcher.go --- old/grype-0.89.0/grype/matcher/java/matcher.go 2025-03-06 17:12:29.000000000 +0100 +++ new/grype-0.89.1/grype/matcher/java/matcher.go 2025-03-11 15:55:51.000000000 +0100 @@ -59,8 +59,7 @@ if strings.Contains(err.Error(), "no artifact found") { log.Debugf("no upstream maven artifact found for %s", p.Name) } else { - log.WithFields("package", p.Name, "error", err).Error("failed to resolve package details with maven") - return nil, nil, fmt.Errorf("resolving package details with maven: %w", err) + return nil, nil, match.NewFatalError(match.JavaMatcher, fmt.Errorf("resolving details for package %q with maven: %w", p.Name, err)) } } else { matches = append(matches, upstreamMatches...) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/grype-0.89.0/grype/matcher/mock/matcher.go new/grype-0.89.1/grype/matcher/mock/matcher.go --- old/grype-0.89.0/grype/matcher/mock/matcher.go 1970-01-01 01:00:00.000000000 +0100 +++ new/grype-0.89.1/grype/matcher/mock/matcher.go 2025-03-11 15:55:51.000000000 +0100 @@ -0,0 +1,45 @@ +package mock + +import ( + "errors" + + "github.com/anchore/grype/grype/match" + "github.com/anchore/grype/grype/pkg" + "github.com/anchore/grype/grype/vulnerability" + syftPkg "github.com/anchore/syft/syft/pkg" +) + +// 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) + +// Matcher is a mock implementation of the match.Matcher interface. This is +// intended for testing purposes only. +type Matcher struct { + typ syftPkg.Type + matchFunc MatchFunc +} + +// New creates a new mock Matcher with the given type and match function. +func New(typ syftPkg.Type, matchFunc MatchFunc) *Matcher { + return &Matcher{ + typ: typ, + matchFunc: matchFunc, + } +} + +func (m Matcher) PackageTypes() []syftPkg.Type { + return []syftPkg.Type{m.typ} +} + +func (m Matcher) Type() match.MatcherType { + return "MOCK" +} + +func (m Matcher) Match(vp vulnerability.Provider, p pkg.Package) ([]match.Match, []match.IgnoredMatch, error) { + if m.matchFunc != nil { + return m.matchFunc(vp, p) + } + + return nil, nil, errors.New("no match function provided") +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/grype-0.89.0/grype/vulnerability/metadata.go new/grype-0.89.1/grype/vulnerability/metadata.go --- old/grype-0.89.0/grype/vulnerability/metadata.go 2025-03-06 17:12:29.000000000 +0100 +++ new/grype-0.89.1/grype/vulnerability/metadata.go 2025-03-11 15:55:51.000000000 +0100 @@ -6,10 +6,10 @@ type Metadata struct { ID string - DataSource string + DataSource string // the primary reference URL, i.e. where the data originated Namespace string Severity string - URLs []string + URLs []string // secondary reference URLs a vulnerability may provide Description string Cvss []Cvss KnownExploited []KnownExploited diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/grype-0.89.0/grype/vulnerability_matcher.go new/grype-0.89.1/grype/vulnerability_matcher.go --- old/grype-0.89.0/grype/vulnerability_matcher.go 2025-03-06 17:12:29.000000000 +0100 +++ new/grype-0.89.1/grype/vulnerability_matcher.go 2025-03-11 15:55:51.000000000 +0100 @@ -64,7 +64,11 @@ } }() - remainingMatches, ignoredMatches = m.findDBMatches(pkgs, context, progressMonitor) + remainingMatches, ignoredMatches, err = m.findDBMatches(pkgs, context, progressMonitor) + if err != nil { + err = fmt.Errorf("unable to find matches against vulnerability database: %w", err) + return remainingMatches, ignoredMatches, err + } remainingMatches, ignoredMatches, err = m.findVEXMatches(context, remainingMatches, ignoredMatches, progressMonitor) if err != nil { @@ -84,13 +88,18 @@ return remainingMatches, ignoredMatches, nil } -func (m *VulnerabilityMatcher) findDBMatches(pkgs []pkg.Package, context pkg.Context, progressMonitor *monitorWriter) (*match.Matches, []match.IgnoredMatch) { +func (m *VulnerabilityMatcher) findDBMatches(pkgs []pkg.Package, context pkg.Context, progressMonitor *monitorWriter) (*match.Matches, []match.IgnoredMatch, error) { var ignoredMatches []match.IgnoredMatch log.Trace("finding matches against DB") matches, err := m.searchDBForMatches(context.Distro, pkgs, progressMonitor) if err != nil { - // errors returned from matchers during searchDBForMatches were being logged and not returned, so just log them here + if match.IsFatalError(err) { + return nil, nil, err + } + + // other errors returned from matchers during searchDBForMatches were being + // logged and not returned, so just log them here log.WithFields("error", err).Debug("error(s) returned from searchDBForMatches") } @@ -111,7 +120,7 @@ ignoredMatches = m.mergeIgnoredMatches(originalIgnoredMatches, ignoredMatches) } - return &matches, ignoredMatches + return &matches, ignoredMatches, nil } func (m *VulnerabilityMatcher) mergeIgnoredMatches(allIgnoredMatches ...[]match.IgnoredMatch) []match.IgnoredMatch { @@ -133,17 +142,16 @@ packages []pkg.Package, progressMonitor *monitorWriter, ) (match.Matches, error) { - var errs error var allMatches []match.Match var allIgnored []match.IgnoredMatch matcherIndex, defaultMatcher := newMatcherIndex(m.Matchers) var d *distro.Distro if release != nil { - d, errs = distro.NewFromRelease(*release) - if errs != nil { - log.Warnf("unable to determine linux distribution: %+v", errs) - errs = nil + var err error + d, err = distro.NewFromRelease(*release) + if err != nil { + log.Warnf("unable to determine linux distribution: %+v", err) } if d != nil && d.Disabled() { log.Warnf("unsupported linux distribution: %s", d.Name()) @@ -154,6 +162,8 @@ if defaultMatcher == nil { defaultMatcher = stock.NewStockMatcher(stock.MatcherConfig{UseCPEs: true}) } + + var matcherErrs []error for _, p := range packages { progressMonitor.PackagesProcessed.Increment() log.WithFields("package", displayPackage(p)).Trace("searching for vulnerability matches") @@ -171,8 +181,12 @@ for _, theMatcher := range matchAgainst { matches, ignoredMatches, err := theMatcher.Match(m.VulnerabilityProvider, p) if err != nil { + if match.IsFatalError(err) { + return match.Matches{}, err + } + log.WithFields("error", err, "package", displayPackage(p)).Warn("matcher returned error") - errs = errors.Join(errs, err) + matcherErrs = append(matcherErrs, err) } allIgnored = append(allIgnored, ignoredMatches...) @@ -206,7 +220,7 @@ // update the total discovered matches after removing all duplicates and ignores progressMonitor.MatchesDiscovered.Set(int64(res.Count())) - return res, errs + return res, errors.Join(matcherErrs...) } func (m *VulnerabilityMatcher) findVEXMatches(context pkg.Context, remainingMatches *match.Matches, ignoredMatches []match.IgnoredMatch, progressMonitor *monitorWriter) (*match.Matches, []match.IgnoredMatch, error) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/grype-0.89.0/grype/vulnerability_matcher_test.go new/grype-0.89.1/grype/vulnerability_matcher_test.go --- old/grype-0.89.0/grype/vulnerability_matcher_test.go 2025-03-06 17:12:29.000000000 +0100 +++ new/grype-0.89.1/grype/vulnerability_matcher_test.go 2025-03-11 15:55:51.000000000 +0100 @@ -1,6 +1,7 @@ package grype import ( + "errors" "testing" "github.com/google/go-cmp/cmp" @@ -17,6 +18,7 @@ "github.com/anchore/grype/grype/match" "github.com/anchore/grype/grype/matcher" "github.com/anchore/grype/grype/matcher/apk" + matcherMock "github.com/anchore/grype/grype/matcher/mock" "github.com/anchore/grype/grype/matcher/ruby" "github.com/anchore/grype/grype/pkg" "github.com/anchore/grype/grype/pkg/qualifier" @@ -250,7 +252,6 @@ { name: "no matches", fields: fields{ - //Store: str, Matchers: matcher.NewDefaultMatchers(matcher.Config{}), }, args: args{ @@ -273,7 +274,6 @@ { name: "matches by exact-direct match (OS)", fields: fields{ - //Store: str, Matchers: matcher.NewDefaultMatchers(matcher.Config{}), }, args: args{ @@ -325,7 +325,6 @@ { name: "fail on severity threshold", fields: fields{ - //Store: str, Matchers: matcher.NewDefaultMatchers(matcher.Config{}), FailSeverity: func() *vulnerability.Severity { x := vulnerability.LowSeverity @@ -381,7 +380,6 @@ { name: "pass on severity threshold with VEX", fields: fields{ - //Store: str, Matchers: matcher.NewDefaultMatchers(matcher.Config{}), FailSeverity: func() *vulnerability.Severity { x := vulnerability.LowSeverity @@ -464,7 +462,6 @@ { name: "matches by exact-direct match (language)", fields: fields{ - //Store: str, Matchers: matcher.NewDefaultMatchers(matcher.Config{ Ruby: ruby.MatcherConfig{ UseCPEs: true, @@ -561,7 +558,6 @@ { name: "normalize by cve", fields: fields{ - //Store: str, Matchers: matcher.NewDefaultMatchers( matcher.Config{ Ruby: ruby.MatcherConfig{ @@ -645,7 +641,6 @@ { name: "normalize by cve -- ignore GHSA", fields: fields{ - //Store: str, Matchers: matcher.NewDefaultMatchers( matcher.Config{ Ruby: ruby.MatcherConfig{ @@ -758,7 +753,6 @@ { name: "normalize by cve -- ignore CVE", fields: fields{ - //Store: str, Matchers: matcher.NewDefaultMatchers( matcher.Config{ Ruby: ruby.MatcherConfig{ @@ -878,7 +872,6 @@ { name: "ignore CVE (not normalized by CVE)", fields: fields{ - //Store: str, Matchers: matcher.NewDefaultMatchers(matcher.Config{ Ruby: ruby.MatcherConfig{ UseCPEs: true, @@ -985,6 +978,7 @@ wantErr: nil, }, } + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { m := &VulnerabilityMatcher{ @@ -1031,6 +1025,61 @@ }) } } + +func Test_fatalErrors(t *testing.T) { + tests := []struct { + name string + matcherFunc matcherMock.MatchFunc + assertErr assert.ErrorAssertionFunc + }{ + { + name: "no error", + matcherFunc: func(_ vulnerability.Provider, _ pkg.Package) ([]match.Match, []match.IgnoredMatch, error) { + return nil, nil, nil + }, + assertErr: assert.NoError, + }, + { + name: "non-fatal error", + matcherFunc: func(_ vulnerability.Provider, _ pkg.Package) ([]match.Match, []match.IgnoredMatch, error) { + return nil, nil, errors.New("some error") + }, + assertErr: assert.NoError, + }, + { + name: "fatal error", + matcherFunc: func(_ vulnerability.Provider, _ pkg.Package) ([]match.Match, []match.IgnoredMatch, error) { + return nil, nil, match.NewFatalError(match.UnknownMatcherType, errors.New("some error")) + }, + assertErr: assert.Error, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + m := &VulnerabilityMatcher{ + Matchers: []match.Matcher{matcherMock.New(syftPkg.JavaPkg, tt.matcherFunc)}, + } + + _, _, err := m.FindMatches([]pkg.Package{ + { + Name: "foo", + Version: "1.2.3", + Type: syftPkg.JavaPkg, + }, + }, + pkg.Context{ + Distro: &linux.Release{ + ID: "debian", + VersionID: "8", + }, + }, + ) + + tt.assertErr(t, err) + }) + } +} func Test_indexFalsePositivesByLocation(t *testing.T) { cases := []struct { ++++++ grype.obsinfo ++++++ --- /var/tmp/diff_new_pack.SYxvCJ/_old 2025-03-14 23:52:18.121155285 +0100 +++ /var/tmp/diff_new_pack.SYxvCJ/_new 2025-03-14 23:52:18.125155451 +0100 @@ -1,5 +1,5 @@ name: grype -version: 0.89.0 -mtime: 1741277549 -commit: 1bf47c38bede40dea7b72bbe4712191820f1aa15 +version: 0.89.1 +mtime: 1741704951 +commit: 718ea3060267edcae7b10a9bf16c0acdad10820a ++++++ vendor.tar.gz ++++++ /work/SRC/openSUSE:Factory/grype/vendor.tar.gz /work/SRC/openSUSE:Factory/.grype.new.19136/vendor.tar.gz differ: char 5, line 1