From 4e8df15b345a29bd53a55a26a1a7fefba885d53a Mon Sep 17 00:00:00 2001 From: James Neate Date: Sat, 6 May 2023 03:23:40 +0100 Subject: [PATCH] feat: include file location in table output (#1199) Signed-off-by: James Neate --- .../snapshot/TestCycloneDxPresenterDir.golden | 51 ++++++++++++- .../TestCycloneDxPresenterImage.golden | 51 ++++++++++++- .../snapshot/TestJsonDirsPresenter.golden | 63 ++++++++++++++++ .../snapshot/TestJsonImgsPresenter.golden | 63 ++++++++++++++++ grype/presenter/models/document_test.go | 15 +++- grype/presenter/models/metadata_mock.go | 17 ++++- grype/presenter/models/models_helpers.go | 40 +++++++++- grype/presenter/sarif/presenter_test.go | 17 ++++- .../TestSarifPresenter_directory.golden | 39 ++++++++++ .../snapshot/TestSarifPresenter_image.golden | 45 ++++++++++++ grype/presenter/table/presenter.go | 17 ++++- grype/presenter/table/presenter_test.go | 73 ++++++++++++++----- .../snapshot/TestTablePresenter.golden | 7 +- .../snapshot/TestPresenter_Present.golden | 5 ++ 14 files changed, 462 insertions(+), 41 deletions(-) diff --git a/grype/presenter/cyclonedx/test-fixtures/snapshot/TestCycloneDxPresenterDir.golden b/grype/presenter/cyclonedx/test-fixtures/snapshot/TestCycloneDxPresenterDir.golden index 9db52f3b476..692afbe448b 100644 --- a/grype/presenter/cyclonedx/test-fixtures/snapshot/TestCycloneDxPresenterDir.golden +++ b/grype/presenter/cyclonedx/test-fixtures/snapshot/TestCycloneDxPresenterDir.golden @@ -2,10 +2,10 @@ "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.4", - "serialNumber": "urn:uuid:f701dea7-2715-48eb-8d63-878377007e65", + "serialNumber": "urn:uuid:716ad06c-2cad-4ffd-a507-08862a89959a", "version": 1, "metadata": { - "timestamp": "2023-05-04T09:41:30-04:00", + "timestamp": "2023-05-06T03:07:35+01:00", "tools": [ { "vendor": "anchore", @@ -48,11 +48,28 @@ "value": "/foo/bar/somefile-2.txt" } ] + }, + { + "bom-ref": "a8d804be757ae96", + "type": "library", + "name": "package-3", + "version": "3.3.3", + "cpe": "cpe:2.3:a:anchore:engine:3.3.3:*:*:python:*:*:*:*", + "properties": [ + { + "name": "syft:package:type", + "value": "npm" + }, + { + "name": "syft:location:0:path", + "value": "/foo/bar/somefile-3.txt" + } + ] } ], "vulnerabilities": [ { - "bom-ref": "urn:uuid:befb74e5-738d-4b2c-adf2-03d276553bca", + "bom-ref": "urn:uuid:61854d6b-1741-4369-b975-b2cad5f9115a", "id": "CVE-1999-0001", "source": {}, "references": [ @@ -78,7 +95,7 @@ ] }, { - "bom-ref": "urn:uuid:9cf43de2-c92a-4f29-add6-29bdd71a0285", + "bom-ref": "urn:uuid:0289344e-4b40-4418-b399-9a709d13819f", "id": "CVE-1999-0002", "source": {}, "references": [ @@ -102,6 +119,32 @@ "ref": "b4013a965511376c" } ] + }, + { + "bom-ref": "urn:uuid:31c2575e-43eb-43e6-bcfa-fc70c36b61e6", + "id": "CVE-1999-0003", + "source": {}, + "references": [ + { + "id": "CVE-1999-0003", + "source": {} + } + ], + "ratings": [ + { + "score": 1, + "severity": "high", + "method": "CVSSv3", + "vector": "vector" + } + ], + "description": "1999-03 description", + "advisories": [], + "affects": [ + { + "ref": "f45d1ab14d63730d" + } + ] } ] } diff --git a/grype/presenter/cyclonedx/test-fixtures/snapshot/TestCycloneDxPresenterImage.golden b/grype/presenter/cyclonedx/test-fixtures/snapshot/TestCycloneDxPresenterImage.golden index ba5b2c47aaa..0652ad068d8 100644 --- a/grype/presenter/cyclonedx/test-fixtures/snapshot/TestCycloneDxPresenterImage.golden +++ b/grype/presenter/cyclonedx/test-fixtures/snapshot/TestCycloneDxPresenterImage.golden @@ -2,10 +2,10 @@ "$schema": "http://cyclonedx.org/schema/bom-1.4.schema.json", "bomFormat": "CycloneDX", "specVersion": "1.4", - "serialNumber": "urn:uuid:102e3928-5e9e-4352-bdfe-b9eb64b837f8", + "serialNumber": "urn:uuid:17d74ef5-13ca-4c95-a8da-cb30698d2098", "version": 1, "metadata": { - "timestamp": "2023-05-04T09:41:30-04:00", + "timestamp": "2023-05-06T03:07:35+01:00", "tools": [ { "vendor": "anchore", @@ -48,11 +48,28 @@ "value": "/foo/bar/somefile-2.txt" } ] + }, + { + "bom-ref": "a8d804be757ae96", + "type": "library", + "name": "package-3", + "version": "3.3.3", + "cpe": "cpe:2.3:a:anchore:engine:3.3.3:*:*:python:*:*:*:*", + "properties": [ + { + "name": "syft:package:type", + "value": "npm" + }, + { + "name": "syft:location:0:path", + "value": "/foo/bar/somefile-3.txt" + } + ] } ], "vulnerabilities": [ { - "bom-ref": "urn:uuid:e082487a-f943-4d4a-8f7c-020d4b0838c4", + "bom-ref": "urn:uuid:04040d97-022e-4ffa-bb3d-225a22641a46", "id": "CVE-1999-0001", "source": {}, "references": [ @@ -78,7 +95,7 @@ ] }, { - "bom-ref": "urn:uuid:3d8b0870-5c57-4063-b30d-56102dd49ec1", + "bom-ref": "urn:uuid:778faaaf-dfca-4cb6-adc1-4da361a2f95d", "id": "CVE-1999-0002", "source": {}, "references": [ @@ -102,6 +119,32 @@ "ref": "b4013a965511376c" } ] + }, + { + "bom-ref": "urn:uuid:fa1f0294-6d50-4f81-96ff-9d172332a31a", + "id": "CVE-1999-0003", + "source": {}, + "references": [ + { + "id": "CVE-1999-0003", + "source": {} + } + ], + "ratings": [ + { + "score": 1, + "severity": "high", + "method": "CVSSv3", + "vector": "vector" + } + ], + "description": "1999-03 description", + "advisories": [], + "affects": [ + { + "ref": "f45d1ab14d63730d" + } + ] } ] } diff --git a/grype/presenter/json/test-fixtures/snapshot/TestJsonDirsPresenter.golden b/grype/presenter/json/test-fixtures/snapshot/TestJsonDirsPresenter.golden index 840e58c3e60..c0d247f70c5 100644 --- a/grype/presenter/json/test-fixtures/snapshot/TestJsonDirsPresenter.golden +++ b/grype/presenter/json/test-fixtures/snapshot/TestJsonDirsPresenter.golden @@ -132,6 +132,69 @@ "purl": "", "upstreams": [] } + }, + { + "vulnerability": { + "id": "CVE-1999-0003", + "dataSource": "", + "severity": "High", + "urls": [], + "description": "1999-03 description", + "cvss": [ + { + "version": "3.0", + "vector": "vector", + "metrics": { + "baseScore": 1, + "exploitabilityScore": 2, + "impactScore": 3 + }, + "vendorMetadata": { + "BaseSeverity": "Low", + "Status": "verified" + } + } + ], + "fix": { + "versions": [], + "state": "" + }, + "advisories": [] + }, + "relatedVulnerabilities": [], + "matchDetails": [ + { + "type": "exact-indirect-match", + "matcher": "javascript-matcher", + "searchedBy": { + "cpe": "somecpe" + }, + "found": { + "constraint": "somecpe" + } + } + ], + "artifact": { + "id": "f45d1ab14d63730d", + "name": "package-3", + "version": "3.3.3", + "type": "npm", + "locations": [ + { + "path": "/foo/bar/somefile-3.txt" + } + ], + "language": "", + "licenses": [ + "MIT", + "Apache-2.0" + ], + "cpes": [ + "cpe:2.3:a:anchore:engine:3.3.3:*:*:python:*:*:*:*" + ], + "purl": "", + "upstreams": [] + } } ], "source": { diff --git a/grype/presenter/json/test-fixtures/snapshot/TestJsonImgsPresenter.golden b/grype/presenter/json/test-fixtures/snapshot/TestJsonImgsPresenter.golden index fb81e431ce9..53a6ac946be 100644 --- a/grype/presenter/json/test-fixtures/snapshot/TestJsonImgsPresenter.golden +++ b/grype/presenter/json/test-fixtures/snapshot/TestJsonImgsPresenter.golden @@ -132,6 +132,69 @@ "purl": "", "upstreams": [] } + }, + { + "vulnerability": { + "id": "CVE-1999-0003", + "dataSource": "", + "severity": "High", + "urls": [], + "description": "1999-03 description", + "cvss": [ + { + "version": "3.0", + "vector": "vector", + "metrics": { + "baseScore": 1, + "exploitabilityScore": 2, + "impactScore": 3 + }, + "vendorMetadata": { + "BaseSeverity": "Low", + "Status": "verified" + } + } + ], + "fix": { + "versions": [], + "state": "" + }, + "advisories": [] + }, + "relatedVulnerabilities": [], + "matchDetails": [ + { + "type": "exact-indirect-match", + "matcher": "javascript-matcher", + "searchedBy": { + "cpe": "somecpe" + }, + "found": { + "constraint": "somecpe" + } + } + ], + "artifact": { + "id": "f45d1ab14d63730d", + "name": "package-3", + "version": "3.3.3", + "type": "npm", + "locations": [ + { + "path": "/foo/bar/somefile-3.txt" + } + ], + "language": "", + "licenses": [ + "MIT", + "Apache-2.0" + ], + "cpes": [ + "cpe:2.3:a:anchore:engine:3.3.3:*:*:python:*:*:*:*" + ], + "purl": "", + "upstreams": [] + } } ], "source": { diff --git a/grype/presenter/models/document_test.go b/grype/presenter/models/document_test.go index dc0031f4881..616d2affcdb 100644 --- a/grype/presenter/models/document_test.go +++ b/grype/presenter/models/document_test.go @@ -30,14 +30,21 @@ func TestPackagesAreSorted(t *testing.T) { Type: syftPkg.DebPkg, } + var pkg3 = pkg.Package{ + ID: "package-3-id", + Name: "package-3", + Version: "3.3.3", + Type: syftPkg.NpmPkg, + } + var match1 = match.Match{ Vulnerability: vulnerability.Vulnerability{ ID: "CVE-1999-0003", }, - Package: pkg1, + Package: pkg3, Details: match.Details{ { - Type: match.ExactDirectMatch, + Type: match.ExactIndirectMatch, }, }, } @@ -46,7 +53,7 @@ func TestPackagesAreSorted(t *testing.T) { Vulnerability: vulnerability.Vulnerability{ ID: "CVE-1999-0002", }, - Package: pkg1, + Package: pkg2, Details: match.Details{ { Type: match.ExactIndirectMatch, @@ -69,7 +76,7 @@ func TestPackagesAreSorted(t *testing.T) { matches := match.NewMatches() matches.Add(match1, match2, match3) - packages := []pkg.Package{pkg1, pkg2} + packages := []pkg.Package{pkg1, pkg2, pkg3} ctx := pkg.Context{ Source: &syftSource.Metadata{ diff --git a/grype/presenter/models/metadata_mock.go b/grype/presenter/models/metadata_mock.go index 326fec60f9e..48c581d6f99 100644 --- a/grype/presenter/models/metadata_mock.go +++ b/grype/presenter/models/metadata_mock.go @@ -55,9 +55,24 @@ func NewMetadataMock() *MetadataMock { }, }, "CVE-1999-0003": { - "source-1": { + "source-3": { Description: "1999-03 description", Severity: "High", + Cvss: []vulnerability.Cvss{ + { + Metrics: vulnerability.NewCvssMetrics( + 1, + 2, + 3, + ), + Vector: "vector", + Version: "3.0", + VendorMetadata: MockVendorMetadata{ + BaseSeverity: "Low", + Status: "verified", + }, + }, + }, }, }, }, diff --git a/grype/presenter/models/models_helpers.go b/grype/presenter/models/models_helpers.go index b56ebdc333a..19331ddadfb 100644 --- a/grype/presenter/models/models_helpers.go +++ b/grype/presenter/models/models_helpers.go @@ -23,7 +23,7 @@ func GenerateAnalysis(t *testing.T, scheme syftSource.Scheme) (match.Matches, [] t.Helper() packages := generatePackages(t) - matches := generateMatches(t, packages[0], packages[1]) + matches := generateMatches(t, packages[0], packages[1], packages[2]) context := generateContext(t, scheme) return matches, packages, context, NewMetadataMock(), nil, nil @@ -69,7 +69,7 @@ func Redact(s []byte) []byte { return s } -func generateMatches(t *testing.T, p, p2 pkg.Package) match.Matches { +func generateMatches(t *testing.T, p, p2, p3 pkg.Package) match.Matches { t.Helper() matches := []match.Match{ @@ -120,6 +120,26 @@ func generateMatches(t *testing.T, p, p2 pkg.Package) match.Matches { }, }, }, + { + + Vulnerability: vulnerability.Vulnerability{ + ID: "CVE-1999-0003", + Namespace: "source-3", + }, + Package: p3, + Details: []match.Detail{ + { + Type: match.ExactIndirectMatch, + Matcher: match.JavascriptMatcher, + SearchedBy: map[string]interface{}{ + "cpe": "somecpe", + }, + Found: map[string]interface{}{ + "constraint": "somecpe", + }, + }, + }, + }, } collection := match.NewMatches(matches...) @@ -173,6 +193,22 @@ func generatePackages(t *testing.T) []pkg.Package { }, Licenses: []string{"MIT", "Apache-2.0"}, }, + { + Name: "package-3", + Version: "3.3.3", + Type: syftPkg.NpmPkg, + Locations: syftSource.NewLocationSet(syftSource.NewVirtualLocation("/foo/bar/somefile-3.txt", "somefile-3.txt")), + CPEs: []cpe.CPE{ + { + Part: "a", + Vendor: "anchore", + Product: "engine", + Version: "3.3.3", + Language: "python", + }, + }, + Licenses: []string{"MIT", "Apache-2.0"}, + }, } updatedPkgs := make([]pkg.Package, 0, len(pkgs)) diff --git a/grype/presenter/sarif/presenter_test.go b/grype/presenter/sarif/presenter_test.go index a83fbc7c1e8..e3b9a218c73 100644 --- a/grype/presenter/sarif/presenter_test.go +++ b/grype/presenter/sarif/presenter_test.go @@ -205,6 +205,7 @@ func TestToSarifReport(t *testing.T) { locations: map[string]string{ "CVE-1999-0001-package-1": "/some/path/somefile-1.txt", "CVE-1999-0002-package-2": "/some/path/somefile-2.txt", + "CVE-1999-0003-package-3": "/some/path/somefile-3.txt", }, }, { @@ -213,6 +214,7 @@ func TestToSarifReport(t *testing.T) { locations: map[string]string{ "CVE-1999-0001-package-1": "image/somefile-1.txt", "CVE-1999-0002-package-2": "image/somefile-2.txt", + "CVE-1999-0003-package-3": "image/somefile-3.txt", }, }, } @@ -244,11 +246,12 @@ func TestToSarifReport(t *testing.T) { // Sorted by vulnID, pkg name, ... run := report.Runs[0] - assert.Len(t, run.Tool.Driver.Rules, 2) + assert.Len(t, run.Tool.Driver.Rules, 3) assert.Equal(t, "CVE-1999-0001-package-1", run.Tool.Driver.Rules[0].ID) assert.Equal(t, "CVE-1999-0002-package-2", run.Tool.Driver.Rules[1].ID) + assert.Equal(t, "CVE-1999-0003-package-3", run.Tool.Driver.Rules[2].ID) - assert.Len(t, run.Results, 2) + assert.Len(t, run.Results, 3) result := run.Results[0] assert.Equal(t, "CVE-1999-0001-package-1", *result.RuleID) assert.Len(t, result.Locations, 1) @@ -268,6 +271,16 @@ func TestToSarifReport(t *testing.T) { t.Fatalf("no expected location for %s", *result.RuleID) } assert.Equal(t, expectedLocation, *location.PhysicalLocation.ArtifactLocation.URI) + + result = run.Results[2] + assert.Equal(t, "CVE-1999-0003-package-3", *result.RuleID) + assert.Len(t, result.Locations, 1) + location = result.Locations[0] + expectedLocation, ok = tc.locations[*result.RuleID] + if !ok { + t.Fatalf("no expected location for %s", *result.RuleID) + } + assert.Equal(t, expectedLocation, *location.PhysicalLocation.ArtifactLocation.URI) }) } diff --git a/grype/presenter/sarif/test-fixtures/snapshot/TestSarifPresenter_directory.golden b/grype/presenter/sarif/test-fixtures/snapshot/TestSarifPresenter_directory.golden index c8bb7eca8c4..cba6d290e24 100644 --- a/grype/presenter/sarif/test-fixtures/snapshot/TestSarifPresenter_directory.golden +++ b/grype/presenter/sarif/test-fixtures/snapshot/TestSarifPresenter_directory.golden @@ -44,6 +44,24 @@ "properties": { "security-severity": "1.0" } + }, + { + "id": "CVE-1999-0003-package-3", + "name": "JavascriptMatcherExactIndirectMatch", + "shortDescription": { + "text": "CVE-1999-0003 high vulnerability for package-3 package" + }, + "fullDescription": { + "text": "1999-03 description" + }, + "helpUri": "https://github.com/anchore/grype", + "help": { + "text": "Vulnerability CVE-1999-0003\nSeverity: high\nPackage: package-3\nVersion: 3.3.3\nFix Version: \nType: npm\nLocation: /some/path/somefile-3.txt\nData Namespace: source-3\nLink: CVE-1999-0003", + "markdown": "**Vulnerability CVE-1999-0003**\n| Severity | Package | Version | Fix Version | Type | Location | Data Namespace | Link |\n| --- | --- | --- | --- | --- | --- | --- | --- |\n| high | package-3 | 3.3.3 | | npm | /some/path/somefile-3.txt | source-3 | CVE-1999-0003 |\n" + }, + "properties": { + "security-severity": "1.0" + } } ] } @@ -90,6 +108,27 @@ } } ] + }, + { + "ruleId": "CVE-1999-0003-package-3", + "message": { + "text": "The path /some/path/somefile-3.txt reports package-3 at version 3.3.3 which would result in a vulnerable (npm) package installed" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "/some/path/somefile-3.txt" + }, + "region": { + "startLine": 1, + "startColumn": 1, + "endLine": 1, + "endColumn": 1 + } + } + } + ] } ] } diff --git a/grype/presenter/sarif/test-fixtures/snapshot/TestSarifPresenter_image.golden b/grype/presenter/sarif/test-fixtures/snapshot/TestSarifPresenter_image.golden index 488d7a9ab19..ce25cf07fe3 100644 --- a/grype/presenter/sarif/test-fixtures/snapshot/TestSarifPresenter_image.golden +++ b/grype/presenter/sarif/test-fixtures/snapshot/TestSarifPresenter_image.golden @@ -44,6 +44,24 @@ "properties": { "security-severity": "1.0" } + }, + { + "id": "CVE-1999-0003-package-3", + "name": "JavascriptMatcherExactIndirectMatch", + "shortDescription": { + "text": "CVE-1999-0003 high vulnerability for package-3 package" + }, + "fullDescription": { + "text": "1999-03 description" + }, + "helpUri": "https://github.com/anchore/grype", + "help": { + "text": "Vulnerability CVE-1999-0003\nSeverity: high\nPackage: package-3\nVersion: 3.3.3\nFix Version: \nType: npm\nLocation: somefile-3.txt\nData Namespace: source-3\nLink: CVE-1999-0003", + "markdown": "**Vulnerability CVE-1999-0003**\n| Severity | Package | Version | Fix Version | Type | Location | Data Namespace | Link |\n| --- | --- | --- | --- | --- | --- | --- | --- |\n| high | package-3 | 3.3.3 | | npm | somefile-3.txt | source-3 | CVE-1999-0003 |\n" + }, + "properties": { + "security-severity": "1.0" + } } ] } @@ -102,6 +120,33 @@ ] } ] + }, + { + "ruleId": "CVE-1999-0003-package-3", + "message": { + "text": "The path somefile-3.txt reports package-3 at version 3.3.3 which is a vulnerable (npm) package installed in the container" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "image/somefile-3.txt" + }, + "region": { + "startLine": 1, + "startColumn": 1, + "endLine": 1, + "endColumn": 1 + } + }, + "logicalLocations": [ + { + "name": "/foo/bar/somefile-3.txt", + "fullyQualifiedName": "user-input@:/somefile-3.txt" + } + ] + } + ] } ] } diff --git a/grype/presenter/table/presenter.go b/grype/presenter/table/presenter.go index d48e9bf80d8..148b0bb2593 100644 --- a/grype/presenter/table/presenter.go +++ b/grype/presenter/table/presenter.go @@ -13,6 +13,7 @@ import ( "github.com/anchore/grype/grype/pkg" "github.com/anchore/grype/grype/presenter/models" "github.com/anchore/grype/grype/vulnerability" + syftPkg "github.com/anchore/syft/syft/pkg" ) const ( @@ -27,6 +28,13 @@ type Presenter struct { metadataProvider vulnerability.MetadataProvider } +// Set the package type to true to not display the location information for that type +var suppressLocation map[syftPkg.Type]bool = map[syftPkg.Type]bool{ + syftPkg.ApkPkg: true, + syftPkg.DebPkg: true, + syftPkg.RpmPkg: true, +} + // NewPresenter is a *Presenter constructor func NewPresenter(pb models.PresenterConfig) *Presenter { return &Presenter{ @@ -41,7 +49,7 @@ func NewPresenter(pb models.PresenterConfig) *Presenter { func (pres *Presenter) Present(output io.Writer) error { rows := make([][]string, 0) - columns := []string{"Name", "Installed", "Fixed-In", "Type", "Vulnerability", "Severity"} + columns := []string{"Name", "Installed", "Fixed-In", "Type", "Vulnerability", "Severity", "Location"} // Generate rows for matching vulnerabilities for m := range pres.results.Enumerate() { row, err := createRow(m, pres.metadataProvider, "") @@ -137,5 +145,10 @@ func createRow(m match.Match, metadataProvider vulnerability.MetadataProvider, s fixVersion = "" } - return []string{m.Package.Name, m.Package.Version, fixVersion, string(m.Package.Type), m.Vulnerability.ID, severity}, nil + var locationPaths string + if !suppressLocation[m.Package.Type] { + locationPaths = strings.Join(m.Package.Locations.CoordinateSet().Paths(), ",") + } + + return []string{m.Package.Name, m.Package.Version, fixVersion, string(m.Package.Type), m.Vulnerability.ID, severity, locationPaths}, nil } diff --git a/grype/presenter/table/presenter_test.go b/grype/presenter/table/presenter_test.go index bd9dd1a9a2c..6540c3621e7 100644 --- a/grype/presenter/table/presenter_test.go +++ b/grype/presenter/table/presenter_test.go @@ -3,6 +3,7 @@ package table import ( "bytes" "flag" + "strings" "testing" "github.com/go-test/deep" @@ -13,7 +14,6 @@ import ( "github.com/anchore/grype/grype/match" "github.com/anchore/grype/grype/pkg" "github.com/anchore/grype/grype/presenter/models" - "github.com/anchore/grype/grype/vulnerability" syftPkg "github.com/anchore/syft/syft/pkg" "github.com/anchore/syft/syft/source" ) @@ -21,25 +21,32 @@ import ( var update = flag.Bool("update", false, "update the *.golden files for table presenters") func TestCreateRow(t *testing.T) { - pkg1 := pkg.Package{ - ID: "package-1-id", - Name: "package-1", - Version: "1.0.1", - Type: syftPkg.DebPkg, + + matches, _, _, _, _, _ := models.GenerateAnalysis(t, source.ImageScheme) + var match1, match2, match3 match.Match + + for m := range matches.Enumerate() { + switch m.Vulnerability.ID { + case "CVE-1999-0001": + match1 = m + case "CVE-1999-0002": + match2 = m + case "CVE-1999-0003": + match3 = m + } } - match1 := match.Match{ - Vulnerability: vulnerability.Vulnerability{ - ID: "CVE-1999-0001", - Namespace: "source-1", - }, - Package: pkg1, - Details: []match.Detail{ - { - Type: match.ExactDirectMatch, - Matcher: match.DpkgMatcher, - }, + + match4 := match.Match{ + Vulnerability: match2.Vulnerability, + Details: match2.Details, + Package: pkg.Package{ + ID: match2.Package.ID, + Name: match2.Package.Name, + Version: match2.Package.Version, + Type: syftPkg.ApkPkg, }, } + cases := []struct { name string match match.Match @@ -52,14 +59,42 @@ func TestCreateRow(t *testing.T) { match: match1, severitySuffix: "", expectedErr: nil, - expectedRow: []string{match1.Package.Name, match1.Package.Version, "", string(match1.Package.Type), match1.Vulnerability.ID, "Low"}, + expectedRow: []string{match1.Package.Name, match1.Package.Version, "the-next-version", string(match1.Package.Type), match1.Vulnerability.ID, "Low", ""}, }, { name: "create row for suppressed vulnerability", match: match1, severitySuffix: appendSuppressed, expectedErr: nil, - expectedRow: []string{match1.Package.Name, match1.Package.Version, "", string(match1.Package.Type), match1.Vulnerability.ID, "Low (suppressed)"}, + expectedRow: []string{match1.Package.Name, match1.Package.Version, "the-next-version", string(match1.Package.Type), match1.Vulnerability.ID, "Low (suppressed)", ""}, + }, + { + name: "create row for suppressed location (rpm)", + match: match1, + severitySuffix: "", + expectedErr: nil, + expectedRow: []string{match1.Package.Name, match1.Package.Version, "the-next-version", string(match1.Package.Type), match1.Vulnerability.ID, "Low", ""}, + }, + { + name: "create row for suppressed location (deb)", + match: match2, + severitySuffix: "", + expectedErr: nil, + expectedRow: []string{match2.Package.Name, match2.Package.Version, "", string(match2.Package.Type), match2.Vulnerability.ID, "Critical", ""}, + }, + { + name: "create row for location", + match: match3, + severitySuffix: "", + expectedErr: nil, + expectedRow: []string{match3.Package.Name, match3.Package.Version, "", string(match3.Package.Type), match3.Vulnerability.ID, "High", strings.Join(match3.Package.Locations.CoordinateSet().Paths(), ", ")}, + }, + { + name: "create row for suppressed location (apk)", + match: match4, + severitySuffix: "", + expectedErr: nil, + expectedRow: []string{match4.Package.Name, match4.Package.Version, "", string(match4.Package.Type), match4.Vulnerability.ID, "Critical", ""}, }, } diff --git a/grype/presenter/table/test-fixtures/snapshot/TestTablePresenter.golden b/grype/presenter/table/test-fixtures/snapshot/TestTablePresenter.golden index e16b5919029..0a533b809c7 100644 --- a/grype/presenter/table/test-fixtures/snapshot/TestTablePresenter.golden +++ b/grype/presenter/table/test-fixtures/snapshot/TestTablePresenter.golden @@ -1,3 +1,4 @@ -NAME INSTALLED FIXED-IN TYPE VULNERABILITY SEVERITY -package-1 1.1.1 the-next-version rpm CVE-1999-0001 Low -package-2 2.2.2 deb CVE-1999-0002 Critical +NAME INSTALLED FIXED-IN TYPE VULNERABILITY SEVERITY LOCATION +package-1 1.1.1 the-next-version rpm CVE-1999-0001 Low +package-2 2.2.2 deb CVE-1999-0002 Critical +package-3 3.3.3 npm CVE-1999-0003 High /foo/bar/somefile-3.txt diff --git a/grype/presenter/template/test-fixtures/snapshot/TestPresenter_Present.golden b/grype/presenter/template/test-fixtures/snapshot/TestPresenter_Present.golden index 0ac37fa30dc..bff46848180 100644 --- a/grype/presenter/template/test-fixtures/snapshot/TestPresenter_Present.golden +++ b/grype/presenter/template/test-fixtures/snapshot/TestPresenter_Present.golden @@ -9,4 +9,9 @@ Identified distro as centos version 8.0. Package: package-2 version 2.2.2 (deb) CPEs: ["cpe:2.3:a:anchore:engine:2.2.2:*:*:python:*:*:*:*"] Matched by: dpkg-matcher + Vulnerability: CVE-1999-0003 + Severity: High + Package: package-3 version 3.3.3 (npm) + CPEs: ["cpe:2.3:a:anchore:engine:3.3.3:*:*:python:*:*:*:*"] + Matched by: javascript-matcher