diff --git a/grype/matcher/apk/matcher_test.go b/grype/matcher/apk/matcher_test.go index a9b303aa793..569b94a07fb 100644 --- a/grype/matcher/apk/matcher_test.go +++ b/grype/matcher/apk/matcher_test.go @@ -350,6 +350,10 @@ func TestNvdOnlyMatches(t *testing.T) { SearchedBy: search.CPEParameters{ CPEs: []string{"cpe:2.3:a:*:libvncserver:0.9.9:*:*:*:*:*:*:*"}, Namespace: "nvd:cpe", + Package: search.CPEPackageParameter{ + Name: "libvncserver", + Version: "0.9.9", + }, }, Found: search.CPEResult{ CPEs: []string{vulnFound.CPEs[0].BindToFmtString()}, @@ -425,6 +429,10 @@ func TestNvdMatchesProperVersionFiltering(t *testing.T) { SearchedBy: search.CPEParameters{ CPEs: []string{"cpe:2.3:a:*:libvncserver:0.9.11:*:*:*:*:*:*:*"}, Namespace: "nvd:cpe", + Package: search.CPEPackageParameter{ + Name: "libvncserver", + Version: "0.9.11-r10", + }, }, Found: search.CPEResult{ CPEs: []string{vulnFound.CPEs[0].BindToFmtString()}, @@ -679,6 +687,10 @@ func TestNVDMatchBySourceIndirection(t *testing.T) { SearchedBy: search.CPEParameters{ CPEs: []string{"cpe:2.3:a:musl:musl:*:*:*:*:*:*:*:*"}, Namespace: "nvd:cpe", + Package: search.CPEPackageParameter{ + Name: "musl", + Version: "1.3.2-r0", + }, }, Found: search.CPEResult{ CPEs: []string{vulnFound.CPEs[0].BindToFmtString()}, diff --git a/grype/search/cpe.go b/grype/search/cpe.go index b962598d6c9..d9d97dd0b6a 100644 --- a/grype/search/cpe.go +++ b/grype/search/cpe.go @@ -17,9 +17,15 @@ import ( syftPkg "github.com/anchore/syft/syft/pkg" ) +type CPEPackageParameter struct { + Name string `json:"name"` + Version string `json:"version"` +} + type CPEParameters struct { Namespace string `json:"namespace"` CPEs []string `json:"cpes"` + Package CPEPackageParameter } func (i *CPEParameters) Merge(other CPEParameters) error { @@ -147,6 +153,10 @@ func addNewMatch(matchesByFingerprint map[match.Fingerprint]match.Match, vuln vu CPEs: []string{ searchedByCPE.BindToFmtString(), }, + Package: CPEPackageParameter{ + Name: p.Name, + Version: p.Version, + }, }, Found: CPEResult{ VulnerabilityID: vuln.ID, diff --git a/grype/search/cpe_test.go b/grype/search/cpe_test.go index 70ead138ffe..e09591f4f2d 100644 --- a/grype/search/cpe_test.go +++ b/grype/search/cpe_test.go @@ -197,6 +197,10 @@ func TestFindMatchesByPackageCPE(t *testing.T) { SearchedBy: CPEParameters{ Namespace: "nvd:cpe", CPEs: []string{"cpe:2.3:*:activerecord:activerecord:3.7.5:rando4:*:re:*:rails:*:*"}, + Package: CPEPackageParameter{ + Name: "activerecord", + Version: "3.7.5", + }, }, Found: CPEResult{ CPEs: []string{"cpe:2.3:*:activerecord:activerecord:*:*:*:*:*:rails:*:*"}, @@ -247,6 +251,10 @@ func TestFindMatchesByPackageCPE(t *testing.T) { "cpe:2.3:*:activerecord:activerecord:3.7.3:rando4:*:re:*:rails:*:*", }, Namespace: "nvd:cpe", + Package: CPEPackageParameter{ + Name: "activerecord", + Version: "3.7.3", + }, }, Found: CPEResult{ CPEs: []string{"cpe:2.3:*:activerecord:activerecord:*:*:*:*:*:rails:*:*"}, @@ -280,6 +288,10 @@ func TestFindMatchesByPackageCPE(t *testing.T) { SearchedBy: CPEParameters{ CPEs: []string{"cpe:2.3:*:activerecord:activerecord:3.7.3:rando1:*:ra:*:ruby:*:*"}, Namespace: "nvd:cpe", + Package: CPEPackageParameter{ + Name: "activerecord", + Version: "3.7.3", + }, }, Found: CPEResult{ CPEs: []string{"cpe:2.3:*:activerecord:activerecord:*:*:*:*:*:ruby:*:*"}, @@ -325,6 +337,10 @@ func TestFindMatchesByPackageCPE(t *testing.T) { SearchedBy: CPEParameters{ CPEs: []string{"cpe:2.3:*:*:activerecord:4.0.1:*:*:*:*:*:*:*"}, Namespace: "nvd:cpe", + Package: CPEPackageParameter{ + Name: "activerecord", + Version: "4.0.1", + }, }, Found: CPEResult{ CPEs: []string{"cpe:2.3:*:activerecord:activerecord:4.0.1:*:*:*:*:*:*:*"}, @@ -378,6 +394,10 @@ func TestFindMatchesByPackageCPE(t *testing.T) { SearchedBy: CPEParameters{ CPEs: []string{"cpe:2.3:*:awesome:awesome:98SE1:rando1:*:ra:*:dunno:*:*"}, Namespace: "nvd:cpe", + Package: CPEPackageParameter{ + Name: "awesome", + Version: "98SE1", + }, }, Found: CPEResult{ CPEs: []string{"cpe:2.3:*:awesome:awesome:*:*:*:*:*:*:*:*"}, @@ -424,6 +444,10 @@ func TestFindMatchesByPackageCPE(t *testing.T) { SearchedBy: CPEParameters{ CPEs: []string{"cpe:2.3:*:multiple:multiple:1.0:*:*:*:*:*:*:*"}, Namespace: "nvd:cpe", + Package: CPEPackageParameter{ + Name: "multiple", + Version: "1.0", + }, }, Found: CPEResult{ CPEs: []string{ @@ -484,6 +508,10 @@ func TestFindMatchesByPackageCPE(t *testing.T) { SearchedBy: CPEParameters{ CPEs: []string{"cpe:2.3:*:sw:sw:*:*:*:*:*:*:*:*"}, Namespace: "nvd:cpe", + Package: CPEPackageParameter{ + Name: "sw", + Version: "0.1", + }, }, Found: CPEResult{ CPEs: []string{ @@ -536,6 +564,10 @@ func TestFindMatchesByPackageCPE(t *testing.T) { SearchedBy: CPEParameters{ CPEs: []string{"cpe:2.3:*:funfun:funfun:*:*:*:*:*:python:*:*"}, Namespace: "nvd:cpe", + Package: CPEPackageParameter{ + Name: "funfun", + Version: "5.2.1", + }, }, Found: CPEResult{ CPEs: []string{ @@ -583,6 +615,10 @@ func TestFindMatchesByPackageCPE(t *testing.T) { SearchedBy: CPEParameters{ CPEs: []string{"cpe:2.3:a:handlebarsjs:handlebars:*:*:*:*:*:*:*:*"}, Namespace: "nvd:cpe", + Package: CPEPackageParameter{ + Name: "handlebars", + Version: "0.1", + }, }, Found: CPEResult{ CPEs: []string{ @@ -629,6 +665,10 @@ func TestFindMatchesByPackageCPE(t *testing.T) { SearchedBy: CPEParameters{ CPEs: []string{"cpe:2.3:a:handlebarsjs:handlebars:*:*:*:*:*:*:*:*"}, Namespace: "nvd:cpe", + Package: CPEPackageParameter{ + Name: "handlebars", + Version: "0.1", + }, }, Found: CPEResult{ CPEs: []string{ diff --git a/grype/search/language.go b/grype/search/language.go index 8b0f154a657..57612c45dac 100644 --- a/grype/search/language.go +++ b/grype/search/language.go @@ -46,6 +46,10 @@ func ByPackageLanguage(store vulnerability.ProviderByLanguage, d *distro.Distro, SearchedBy: map[string]interface{}{ "language": string(p.Language), "namespace": vuln.Namespace, + "package": map[string]string{ + "name": p.Name, + "version": p.Version, + }, }, Found: map[string]interface{}{ "vulnerabilityID": vuln.ID, diff --git a/grype/search/language_test.go b/grype/search/language_test.go index 8e8f59351bd..9c610a73df9 100644 --- a/grype/search/language_test.go +++ b/grype/search/language_test.go @@ -79,6 +79,7 @@ func expectedMatch(p pkg.Package, constraint string) []match.Match { SearchedBy: map[string]interface{}{ "language": "ruby", "namespace": "github:ruby", + "package": map[string]string{"name": p.Name, "version": p.Version}, }, Found: map[string]interface{}{ "versionConstraint": constraint, diff --git a/grype/vulnerability_matcher_test.go b/grype/vulnerability_matcher_test.go index fde08f091ba..0e856170698 100644 --- a/grype/vulnerability_matcher_test.go +++ b/grype/vulnerability_matcher_test.go @@ -491,6 +491,10 @@ func TestVulnerabilityMatcher_FindMatches(t *testing.T) { 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", @@ -526,6 +530,7 @@ func TestVulnerabilityMatcher_FindMatches(t *testing.T) { 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)", @@ -579,6 +584,20 @@ func TestVulnerabilityMatcher_FindMatches(t *testing.T) { }, 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, + }, { Type: match.CPEMatch, SearchedBy: search.CPEParameters{ @@ -586,6 +605,10 @@ func TestVulnerabilityMatcher_FindMatches(t *testing.T) { 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", @@ -597,19 +620,6 @@ func TestVulnerabilityMatcher_FindMatches(t *testing.T) { Matcher: "ruby-gem-matcher", Confidence: 0.9, }, - { - Type: match.ExactDirectMatch, - SearchedBy: map[string]any{ - "language": "ruby", - "namespace": "github:language:ruby", - }, - Found: map[string]any{ - "versionConstraint": "< 3.7.6 (unknown)", - "vulnerabilityID": "GHSA-2014-fake-3", - }, - Matcher: "ruby-gem-matcher", - Confidence: 1, - }, }, }, ), @@ -661,6 +671,10 @@ func TestVulnerabilityMatcher_FindMatches(t *testing.T) { 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", @@ -731,6 +745,7 @@ func TestVulnerabilityMatcher_FindMatches(t *testing.T) { 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)", @@ -788,6 +803,7 @@ func TestVulnerabilityMatcher_FindMatches(t *testing.T) { 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)", @@ -826,6 +842,10 @@ func TestVulnerabilityMatcher_FindMatches(t *testing.T) { 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", diff --git a/test/integration/match_by_image_test.go b/test/integration/match_by_image_test.go index 2cf83c32c84..75f84cd84ac 100644 --- a/test/integration/match_by_image_test.go +++ b/test/integration/match_by_image_test.go @@ -107,6 +107,10 @@ func addJavascriptMatches(t *testing.T, theSource source.Source, catalog *syftPk SearchedBy: map[string]interface{}{ "language": "javascript", "namespace": "github:language:javascript", + "package": map[string]string{ + "name": thePkg.Name, + "version": thePkg.Version, + }, }, Found: map[string]interface{}{ "versionConstraint": "> 5, < 7.2.1 (unknown)", @@ -144,6 +148,10 @@ func addPythonMatches(t *testing.T, theSource source.Source, catalog *syftPkg.Co SearchedBy: map[string]interface{}{ "language": "python", "namespace": "github:language:python", + "package": map[string]string{ + "name": thePkg.Name, + "version": thePkg.Version, + }, }, Found: map[string]interface{}{ "versionConstraint": "< 2.6.2 (python)", @@ -181,6 +189,10 @@ func addDotnetMatches(t *testing.T, theSource source.Source, catalog *syftPkg.Co SearchedBy: map[string]interface{}{ "language": "dotnet", "namespace": "github:language:dotnet", + "package": map[string]string{ + "name": thePkg.Name, + "version": thePkg.Version, + }, }, Found: map[string]interface{}{ "versionConstraint": ">= 3.7.0.0, < 3.7.12.0 (unknown)", @@ -214,6 +226,10 @@ func addRubyMatches(t *testing.T, theSource source.Source, catalog *syftPkg.Coll SearchedBy: map[string]interface{}{ "language": "ruby", "namespace": "github:language:ruby", + "package": map[string]string{ + "name": thePkg.Name, + "version": thePkg.Version, + }, }, Found: map[string]interface{}{ "versionConstraint": "> 2.0.0, <= 2.1.4 (unknown)", @@ -263,6 +279,10 @@ func addGolangMatches(t *testing.T, theSource source.Source, catalog *syftPkg.Co SearchedBy: map[string]interface{}{ "language": "go", "namespace": "github:language:go", + "package": map[string]string{ + "name": thePkg.Name, + "version": thePkg.Version, + }, }, Found: map[string]interface{}{ "versionConstraint": "< 1.4.0 (unknown)", @@ -306,6 +326,10 @@ func addJavaMatches(t *testing.T, theSource source.Source, catalog *syftPkg.Coll SearchedBy: map[string]interface{}{ "language": "java", "namespace": "github:language:java", + "package": map[string]string{ + "name": thePkg.Name, + "version": thePkg.Version, + }, }, Found: map[string]interface{}{ "versionConstraint": ">= 0.0.1, < 1.2.0 (unknown)", @@ -498,6 +522,10 @@ func addHaskellMatches(t *testing.T, theSource source.Source, catalog *syftPkg.C SearchedBy: map[string]any{ "language": "haskell", "namespace": "github:language:haskell", + "package": map[string]string{ + "name": thePkg.Name, + "version": thePkg.Version, + }, }, Found: map[string]any{ "versionConstraint": "< 0.9.0 (unknown)", diff --git a/test/integration/match_by_sbom_document_test.go b/test/integration/match_by_sbom_document_test.go index 61e239b4ecc..d112f37fd06 100644 --- a/test/integration/match_by_sbom_document_test.go +++ b/test/integration/match_by_sbom_document_test.go @@ -62,6 +62,7 @@ func TestMatchBySBOMDocument(t *testing.T) { SearchedBy: map[string]interface{}{ "language": "python", "namespace": "github:language:python", + "package": map[string]string{"name": "my-package", "version": "1.0.5"}, }, Found: map[string]interface{}{ "versionConstraint": "< 2.0 (python)",