mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-22 07:10:41 -08:00
feat: summarize vulnerabilities in compliance reports (#3651)
This commit is contained in:
2
go.mod
2
go.mod
@@ -8,7 +8,7 @@ require (
|
|||||||
github.com/NYTimes/gziphandler v1.1.1
|
github.com/NYTimes/gziphandler v1.1.1
|
||||||
github.com/alicebob/miniredis/v2 v2.23.0
|
github.com/alicebob/miniredis/v2 v2.23.0
|
||||||
github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986
|
github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986
|
||||||
github.com/aquasecurity/defsec v0.82.10-0.20230222063803-b1b6b5381ea1
|
github.com/aquasecurity/defsec v0.82.11-0.20230227200028-1372c6329e1f
|
||||||
github.com/aquasecurity/go-dep-parser v0.0.0-20230227085514-f6e7eca87043
|
github.com/aquasecurity/go-dep-parser v0.0.0-20230227085514-f6e7eca87043
|
||||||
github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce
|
github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce
|
||||||
github.com/aquasecurity/go-npm-version v0.0.0-20201110091526-0b796d180798
|
github.com/aquasecurity/go-npm-version v0.0.0-20201110091526-0b796d180798
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -315,8 +315,8 @@ github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6
|
|||||||
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
|
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
|
||||||
github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986 h1:2a30xLN2sUZcMXl50hg+PJCIDdJgIvIbVcKqLJ/ZrtM=
|
github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986 h1:2a30xLN2sUZcMXl50hg+PJCIDdJgIvIbVcKqLJ/ZrtM=
|
||||||
github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986/go.mod h1:NT+jyeCzXk6vXR5MTkdn4z64TgGfE5HMLC8qfj5unl8=
|
github.com/aquasecurity/bolt-fixtures v0.0.0-20200903104109-d34e7f983986/go.mod h1:NT+jyeCzXk6vXR5MTkdn4z64TgGfE5HMLC8qfj5unl8=
|
||||||
github.com/aquasecurity/defsec v0.82.10-0.20230222063803-b1b6b5381ea1 h1:SXg+dQbjmays+9+ND8M5YIDgGHjugbUu9Ncq3aYjd/Y=
|
github.com/aquasecurity/defsec v0.82.11-0.20230227200028-1372c6329e1f h1:GMsUbqXjrGzNOyxFGJt/WtJrBFXzQWtJJ2h+uoAUguQ=
|
||||||
github.com/aquasecurity/defsec v0.82.10-0.20230222063803-b1b6b5381ea1/go.mod h1:AJswzQrwesjdpF03Ev7lcPdr5REBJLAmDqjvOitvr94=
|
github.com/aquasecurity/defsec v0.82.11-0.20230227200028-1372c6329e1f/go.mod h1:AJswzQrwesjdpF03Ev7lcPdr5REBJLAmDqjvOitvr94=
|
||||||
github.com/aquasecurity/go-dep-parser v0.0.0-20230227085514-f6e7eca87043 h1:3YbIYXC9/HLODABe2P4v3nPJjK9MEFOtOmnSbiCIXdo=
|
github.com/aquasecurity/go-dep-parser v0.0.0-20230227085514-f6e7eca87043 h1:3YbIYXC9/HLODABe2P4v3nPJjK9MEFOtOmnSbiCIXdo=
|
||||||
github.com/aquasecurity/go-dep-parser v0.0.0-20230227085514-f6e7eca87043/go.mod h1:xx5OX/gVENa5dY60k9EliVvTbUf/EmRw1tJKzdskKGw=
|
github.com/aquasecurity/go-dep-parser v0.0.0-20230227085514-f6e7eca87043/go.mod h1:xx5OX/gVENa5dY60k9EliVvTbUf/EmRw1tJKzdskKGw=
|
||||||
github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce h1:QgBRgJvtEOBtUXilDb1MLi1p1MWoyFDXAu5DEUl5nwM=
|
github.com/aquasecurity/go-gem-version v0.0.0-20201115065557-8eed6fe000ce h1:QgBRgJvtEOBtUXilDb1MLi1p1MWoyFDXAu5DEUl5nwM=
|
||||||
|
|||||||
@@ -521,8 +521,8 @@ func initScannerConfig(opts flag.Options, cacheClient cache.Cache) (ScannerConfi
|
|||||||
opts.ImageConfigScanners = nil
|
opts.ImageConfigScanners = nil
|
||||||
// TODO: define image-config-scanners in the spec
|
// TODO: define image-config-scanners in the spec
|
||||||
if opts.Compliance.Spec.ID == "docker-cis" {
|
if opts.Compliance.Spec.ID == "docker-cis" {
|
||||||
opts.Scanners = nil
|
opts.Scanners = types.Scanners{types.VulnerabilityScanner}
|
||||||
opts.ImageConfigScanners = scanners
|
opts.ImageConfigScanners = types.Scanners{types.MisconfigScanner}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -96,6 +96,8 @@ func scannerByCheckID(checkID string) types.Scanner {
|
|||||||
return types.VulnerabilityScanner
|
return types.VulnerabilityScanner
|
||||||
case strings.HasPrefix(checkID, "avd-"):
|
case strings.HasPrefix(checkID, "avd-"):
|
||||||
return types.MisconfigScanner
|
return types.MisconfigScanner
|
||||||
|
case strings.HasPrefix(checkID, "vuln-"): // custom id for filtering vulnerabilities by severity
|
||||||
|
return types.VulnerabilityScanner
|
||||||
default:
|
default:
|
||||||
return types.UnknownScanner
|
return types.UnknownScanner
|
||||||
}
|
}
|
||||||
|
|||||||
52
pkg/compliance/spec/custom.go
Normal file
52
pkg/compliance/spec/custom.go
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
package spec
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/samber/lo"
|
||||||
|
|
||||||
|
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
|
||||||
|
"github.com/aquasecurity/trivy/pkg/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// We might be going to rewrite these functions in Rego,
|
||||||
|
// but we'll keep them for now until we need flexibility.
|
||||||
|
var customIDs = map[string]func(types.Result) types.Result{
|
||||||
|
"VULN-CRITICAL": filterCriticalVulns,
|
||||||
|
"VULN-HIGH": filterHighVulns,
|
||||||
|
}
|
||||||
|
|
||||||
|
func mapCustomIDsToFilteredResults(result types.Result, checkIDs map[types.Scanner][]string,
|
||||||
|
mapCheckByID map[string]types.Results) {
|
||||||
|
for _, ids := range checkIDs {
|
||||||
|
for _, id := range ids {
|
||||||
|
filterFunc, ok := customIDs[id]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
filtered := filterFunc(result)
|
||||||
|
if filtered.IsEmpty() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
mapCheckByID[id] = types.Results{filtered}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func filterCriticalVulns(result types.Result) types.Result {
|
||||||
|
return filterVulns(result, dbTypes.SeverityCritical)
|
||||||
|
}
|
||||||
|
|
||||||
|
func filterHighVulns(result types.Result) types.Result {
|
||||||
|
return filterVulns(result, dbTypes.SeverityHigh)
|
||||||
|
}
|
||||||
|
|
||||||
|
func filterVulns(result types.Result, severity dbTypes.Severity) types.Result {
|
||||||
|
filtered := lo.Filter(result.Vulnerabilities, func(vuln types.DetectedVulnerability, _ int) bool {
|
||||||
|
return vuln.Severity == severity.String()
|
||||||
|
})
|
||||||
|
return types.Result{
|
||||||
|
Target: result.Target,
|
||||||
|
Class: result.Class,
|
||||||
|
Type: result.Type,
|
||||||
|
Vulnerabilities: filtered,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -35,6 +35,10 @@ func MapSpecCheckIDToFilteredResults(result types.Result, checkIDs map[types.Sca
|
|||||||
Misconfigurations: []types.DetectedMisconfiguration{m},
|
Misconfigurations: []types.DetectedMisconfiguration{m},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Evaluate custom IDs
|
||||||
|
mapCustomIDsToFilteredResults(result, checkIDs, mapCheckByID)
|
||||||
|
|
||||||
return mapCheckByID
|
return mapCheckByID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
|
||||||
"github.com/aquasecurity/trivy/pkg/compliance/spec"
|
"github.com/aquasecurity/trivy/pkg/compliance/spec"
|
||||||
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
ftypes "github.com/aquasecurity/trivy/pkg/fanal/types"
|
||||||
"github.com/aquasecurity/trivy/pkg/types"
|
"github.com/aquasecurity/trivy/pkg/types"
|
||||||
@@ -19,6 +20,7 @@ func TestMapSpecCheckIDToFilteredResults(t *testing.T) {
|
|||||||
},
|
},
|
||||||
types.VulnerabilityScanner: {
|
types.VulnerabilityScanner: {
|
||||||
"CVE-9999-9999",
|
"CVE-9999-9999",
|
||||||
|
"VULN-CRITICAL",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
@@ -96,8 +98,18 @@ func TestMapSpecCheckIDToFilteredResults(t *testing.T) {
|
|||||||
Class: types.ClassLangPkg,
|
Class: types.ClassLangPkg,
|
||||||
Type: ftypes.GoModule,
|
Type: ftypes.GoModule,
|
||||||
Vulnerabilities: []types.DetectedVulnerability{
|
Vulnerabilities: []types.DetectedVulnerability{
|
||||||
{VulnerabilityID: "CVE-9999-0001"},
|
{
|
||||||
{VulnerabilityID: "CVE-9999-9999"},
|
VulnerabilityID: "CVE-9999-0001",
|
||||||
|
Vulnerability: dbTypes.Vulnerability{
|
||||||
|
Severity: "CRITICAL",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
VulnerabilityID: "CVE-9999-9999",
|
||||||
|
Vulnerability: dbTypes.Vulnerability{
|
||||||
|
Severity: "LOW",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
want: map[string]types.Results{
|
want: map[string]types.Results{
|
||||||
@@ -107,7 +119,27 @@ func TestMapSpecCheckIDToFilteredResults(t *testing.T) {
|
|||||||
Class: types.ClassLangPkg,
|
Class: types.ClassLangPkg,
|
||||||
Type: ftypes.GoModule,
|
Type: ftypes.GoModule,
|
||||||
Vulnerabilities: []types.DetectedVulnerability{
|
Vulnerabilities: []types.DetectedVulnerability{
|
||||||
{VulnerabilityID: "CVE-9999-9999"},
|
{
|
||||||
|
VulnerabilityID: "CVE-9999-9999",
|
||||||
|
Vulnerability: dbTypes.Vulnerability{
|
||||||
|
Severity: "LOW",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"VULN-CRITICAL": {
|
||||||
|
{
|
||||||
|
Target: "target",
|
||||||
|
Class: types.ClassLangPkg,
|
||||||
|
Type: ftypes.GoModule,
|
||||||
|
Vulnerabilities: []types.DetectedVulnerability{
|
||||||
|
{
|
||||||
|
VulnerabilityID: "CVE-9999-0001",
|
||||||
|
Vulnerability: dbTypes.Vulnerability{
|
||||||
|
Severity: "CRITICAL",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user