From c6844a73f19dd1908d50cd5dd801ff3059dfa998 Mon Sep 17 00:00:00 2001 From: Kristina Trotsko Date: Fri, 16 Feb 2024 09:39:03 +0100 Subject: [PATCH] feat(report): support for filtering licenses and secrets via rego policy files (#6004) --- contrib/example_policy/basic.rego | 18 +++++ docs/docs/configuration/filtering.md | 7 +- pkg/result/filter.go | 28 ++++++++ pkg/result/filter_test.go | 72 +++++++++++++++++++ ...st-ignore-policy-licenses-and-secrets.rego | 15 ++++ 5 files changed, 137 insertions(+), 3 deletions(-) create mode 100644 pkg/result/testdata/test-ignore-policy-licenses-and-secrets.rego diff --git a/contrib/example_policy/basic.rego b/contrib/example_policy/basic.rego index 361345b2cbc..0cf9f0ea04e 100644 --- a/contrib/example_policy/basic.rego +++ b/contrib/example_policy/basic.rego @@ -56,3 +56,21 @@ ignore { # https://cwe.mitre.org/data/definitions/352.html input.CweIDs[_] == "CWE-352" } + +# Ignore a license +ignore { + input.PkgName == "alpine-baselayout" + input.Name == "GPL-2.0" +} + +# Ignore loose file license +ignore { + input.Name == "AGPL-3.0" + input.FilePath == "/usr/share/grafana/LICENSE" +} + +# Ignore secret +ignore { + input.RuleID == "aws-access-key-id" + input.Match == "AWS_ACCESS_KEY_ID=\"********************\"" +} diff --git a/docs/docs/configuration/filtering.md b/docs/docs/configuration/filtering.md index 428220c87df..ad8c72e4b20 100644 --- a/docs/docs/configuration/filtering.md +++ b/docs/docs/configuration/filtering.md @@ -409,8 +409,8 @@ Total: 0 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 0) |:----------------:|:---------:| | Vulnerability | ✓ | | Misconfiguration | ✓ | -| Secret | | -| License | | +| Secret | ✓ | +| License | ✓ | !!! warning "EXPERIMENTAL" This feature might change without preserving backwards compatibility. @@ -455,7 +455,8 @@ trivy image -f json centos:7 ... ``` -Each individual vulnerability (under `Results.Vulnerabilities`) or Misconfiguration (under `Results.Misconfigurations`) is evaluated for exclusion or inclusion by the `ignore` rule. +Each individual Vulnerability, Misconfiguration, License and Secret (under `Results.Vulnerabilities`, `Results.Misconfigurations`, +`Results.Licenses`, `Results.Secrets`) is evaluated for exclusion or inclusion by the `ignore` rule. The following is a Rego ignore policy that filters out every vulnerability with a specific CWE ID (as seen in the JSON example above): diff --git a/pkg/result/filter.go b/pkg/result/filter.go index d1569f72054..3feb82acc83 100644 --- a/pkg/result/filter.go +++ b/pkg/result/filter.go @@ -288,6 +288,34 @@ func applyPolicy(ctx context.Context, result *types.Result, policyFile string) e } result.Misconfigurations = filteredMisconfs + // Secrets + var filteredSecrets []types.DetectedSecret + for _, scrt := range result.Secrets { + ignored, err := evaluate(ctx, query, scrt) + if err != nil { + return err + } + if ignored { + continue + } + filteredSecrets = append(filteredSecrets, scrt) + } + result.Secrets = filteredSecrets + + // Licenses + var filteredLicenses []types.DetectedLicense + for _, lic := range result.Licenses { + ignored, err := evaluate(ctx, query, lic) + if err != nil { + return err + } + if ignored { + continue + } + filteredLicenses = append(filteredLicenses, lic) + } + result.Licenses = filteredLicenses + return nil } diff --git a/pkg/result/filter_test.go b/pkg/result/filter_test.go index 41eec6efd57..7a809447ad3 100644 --- a/pkg/result/filter_test.go +++ b/pkg/result/filter_test.go @@ -615,6 +615,78 @@ func TestFilter(t *testing.T) { }, }, }, + { + name: "ignore file for licenses and secrets", + args: args{ + report: types.Report{ + Results: types.Results{ + { + Licenses: []types.DetectedLicense{ + { + Name: "GPL-3.0", + Severity: dbTypes.SeverityLow.String(), + FilePath: "usr/share/gcc/python/libstdcxx/v6/__init__.py", + Category: "restricted", + Confidence: 1, + }, + { + Name: "GPL-3.0", + Severity: dbTypes.SeverityLow.String(), + FilePath: "usr/share/gcc/python/libstdcxx/v6/printers.py", + Category: "restricted", + Confidence: 1, + }, + }, + Secrets: []types.DetectedSecret{ + { + RuleID: "generic-passed-rule", + Severity: dbTypes.SeverityLow.String(), + Title: "Secret should pass filter", + StartLine: 1, + EndLine: 2, + Match: "*****", + }, + { + RuleID: "generic-ignored-rule", + Severity: dbTypes.SeverityLow.String(), + Title: "Secret should be ignored", + StartLine: 3, + EndLine: 4, + Match: "*****", + }, + }, + }, + }, + }, + severities: []dbTypes.Severity{dbTypes.SeverityLow}, + policyFile: "./testdata/test-ignore-policy-licenses-and-secrets.rego", + }, + want: types.Report{ + Results: types.Results{ + { + Licenses: []types.DetectedLicense{ + { + Name: "GPL-3.0", + Severity: dbTypes.SeverityLow.String(), + FilePath: "usr/share/gcc/python/libstdcxx/v6/__init__.py", + Category: "restricted", + Confidence: 1, + }, + }, + Secrets: []types.DetectedSecret{ + { + RuleID: "generic-passed-rule", + Severity: dbTypes.SeverityLow.String(), + Title: "Secret should pass filter", + StartLine: 1, + EndLine: 2, + Match: "*****", + }, + }, + }, + }, + }, + }, { name: "happy path with duplicates, one with empty fixed version", args: args{ diff --git a/pkg/result/testdata/test-ignore-policy-licenses-and-secrets.rego b/pkg/result/testdata/test-ignore-policy-licenses-and-secrets.rego new file mode 100644 index 00000000000..b53c16a11ff --- /dev/null +++ b/pkg/result/testdata/test-ignore-policy-licenses-and-secrets.rego @@ -0,0 +1,15 @@ +package trivy + +import data.lib.trivy + +default ignore=false + +ignore { + input.Name == "GPL-3.0" + input.FilePath == "usr/share/gcc/python/libstdcxx/v6/printers.py" +} + +ignore { + input.RuleID == "generic-ignored-rule" + input.Title == "Secret should be ignored" +}