From 04535b554ab239b30543ae6514b677d416785ca1 Mon Sep 17 00:00:00 2001 From: Damian E Date: Mon, 4 Mar 2024 10:38:51 +0100 Subject: [PATCH] fix(license): add FilePath to results to allow for license path filtering via trivyignore file (#6215) Co-authored-by: DmitriyLewen <91113035+DmitriyLewen@users.noreply.github.com> Co-authored-by: DmitriyLewen --- docs/docs/configuration/filtering.md | 2 +- pkg/scanner/local/scan.go | 12 +-- pkg/scanner/local/scan_test.go | 121 +++++++++++++++++++++++++++ 3 files changed, 129 insertions(+), 6 deletions(-) diff --git a/docs/docs/configuration/filtering.md b/docs/docs/configuration/filtering.md index df6cc8726934..75e880af4f49 100644 --- a/docs/docs/configuration/filtering.md +++ b/docs/docs/configuration/filtering.md @@ -494,4 +494,4 @@ Please refer to the [VEX documentation](../supply-chain/vex.md) for the details. [^1]: license name is used as id for `.trivyignore.yaml` files. -[^2]: This doesn't work for package licenses. The `path` field can only be used for license files (licenses obtained using the [--license-full flag](../scanner/license.md#full-scanning)). \ No newline at end of file +[^2]: This doesn't work for os package licenses (e.g. apk, dpkg, rpm). For projects which manage dependencies through a dependency file (e.g. go.mod, yarn.lock) `path` should point to that particular file. diff --git a/pkg/scanner/local/scan.go b/pkg/scanner/local/scan.go index 98fc3d4d7571..b5437549c5cc 100644 --- a/pkg/scanner/local/scan.go +++ b/pkg/scanner/local/scan.go @@ -298,7 +298,6 @@ func (s Scanner) scanLicenses(target types.ScanTarget, options types.ScanOptions Confidence: 1.0, }) } - } results = append(results, types.Result{ Target: "OS Packages", @@ -313,10 +312,13 @@ func (s Scanner) scanLicenses(target types.ScanTarget, options types.ScanOptions for _, license := range lib.Licenses { category, severity := scanner.Scan(license) langLicenses = append(langLicenses, types.DetectedLicense{ - Severity: severity, - Category: category, - PkgName: lib.Name, - Name: license, + Severity: severity, + Category: category, + PkgName: lib.Name, + Name: license, + // Lock files use app.FilePath - https://github.com/aquasecurity/trivy/blob/6ccc0a554b07b05fd049f882a1825a0e1e0aabe1/pkg/fanal/types/artifact.go#L245-L246 + // Applications use lib.FilePath - https://github.com/aquasecurity/trivy/blob/6ccc0a554b07b05fd049f882a1825a0e1e0aabe1/pkg/fanal/types/artifact.go#L93-L94 + FilePath: lo.Ternary(lib.FilePath != "", lib.FilePath, app.FilePath), Confidence: 1.0, }) } diff --git a/pkg/scanner/local/scan_test.go b/pkg/scanner/local/scan_test.go index 6677910ed856..3b173957cc23 100644 --- a/pkg/scanner/local/scan_test.go +++ b/pkg/scanner/local/scan_test.go @@ -148,6 +148,127 @@ func TestScanner_Scan(t *testing.T) { Eosl: true, }, }, + { + name: "happy path license scanner", + args: args{ + target: "alpine:latest", + layerIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, + options: types.ScanOptions{ + Scanners: types.Scanners{types.LicenseScanner}, + }, + }, + fixtures: []string{"testdata/fixtures/happy.yaml"}, + applyLayersExpectation: ApplierApplyLayersExpectation{ + Args: ApplierApplyLayersArgs{ + BlobIDs: []string{"sha256:5216338b40a7b96416b8b9858974bbe4acc3096ee60acbc4dfb1ee02aecceb10"}, + }, + Returns: ApplierApplyLayersReturns{ + Detail: ftypes.ArtifactDetail{ + OS: ftypes.OS{ + Family: ftypes.Alpine, + Name: "3.11", + }, + Packages: []ftypes.Package{ + { + Name: "musl", + Version: "1.2.3", + SrcName: "musl", + SrcVersion: "1.2.3", + Licenses: []string{"MIT"}, + Layer: ftypes.Layer{ + DiffID: "sha256:ebf12965380b39889c99a9c02e82ba465f887b45975b6e389d42e9e6a3857888", + }, + }, + }, + Applications: []ftypes.Application{ + { + Type: ftypes.GoModule, + FilePath: "/app/go.mod", + Libraries: []ftypes.Package{ + { + Name: "github.com/google/uuid", + Version: "1.6.0", + FilePath: "", + Layer: ftypes.Layer{ + DiffID: "sha256:0ea33a93585cf1917ba522b2304634c3073654062d5282c1346322967790ef33", + }, + Licenses: []string{"LGPL"}, + }, + }, + }, + { + Type: ftypes.PythonPkg, + FilePath: "", + Libraries: []ftypes.Package{ + { + Name: "urllib3", + Version: "3.2.1", + FilePath: "/usr/lib/python/site-packages/urllib3-3.2.1/METADATA", + Layer: ftypes.Layer{ + DiffID: "sha256:0ea33a93585cf1917ba522b2304634c3073654062d5282c1346322967790ef33", + }, + Licenses: []string{"MIT"}, + }, + }, + }, + }, + }, + }, + }, + wantResults: types.Results{ + { + Target: "OS Packages", + Class: types.ClassLicense, + Licenses: []types.DetectedLicense{ + { + Severity: "UNKNOWN", + Category: "unknown", + PkgName: "musl", + Name: "MIT", + Confidence: 1, + }, + }, + }, + { + Target: "/app/go.mod", + Class: types.ClassLicense, + Licenses: []types.DetectedLicense{ + { + Severity: "UNKNOWN", + Category: "unknown", + PkgName: "github.com/google/uuid", + FilePath: "/app/go.mod", + Name: "LGPL", + Confidence: 1, + Link: "", + }, + }, + }, + { + Target: "Python", + Class: types.ClassLicense, + Licenses: []types.DetectedLicense{ + { + Severity: "UNKNOWN", + Category: "unknown", + PkgName: "urllib3", + FilePath: "/usr/lib/python/site-packages/urllib3-3.2.1/METADATA", + Name: "MIT", + Confidence: 1, + }, + }, + }, + { + Target: "Loose File License(s)", + Class: types.ClassLicenseFile, + }, + }, + wantOS: ftypes.OS{ + Family: "alpine", + Name: "3.11", + Eosl: false, + }, + }, { name: "happy path with list all packages", args: args{