Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

internal/report: detect unused exclusions #90

Merged
merged 1 commit into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions cmd/lava/internal/help/helpdoc.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ the following properties.
- exclusions: list of rules that define what findings should be
excluded from the report. It allows to ignore findings because of
accepted risks, false positives, etc.
- errorOnStaleExclusions: boolean specifying whether Lava should
exit with error when stale exclusions are detected. If not
specified, the default value is false.

The sample below is a full report configuration:

Expand All @@ -160,6 +163,7 @@ The sample below is a full report configuration:
- description: Ignore test certificates.
summary: 'Secret Leaked in Git Repository'
resource: '/testdata/certs/'
errorOnStaleExclusions: true

The exclusion rules support the following filters:

Expand Down
1 change: 1 addition & 0 deletions cmd/lava/internal/scan/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ that have been found.
- 1: Command error
- 2: Syntax error
- 3: Check error
- 4: Stale exclusions
- 100: Informational vulnerabilities found
- 101: Low severity vulnerabilities found
- 102: Medium severity vulnerabilities found
Expand Down
4 changes: 4 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,10 @@ type ReportConfig struct {
// instance, accepted risks, false positives, etc.
Exclusions []Exclusion `yaml:"exclusions"`

// ErrorOnStaleExclusions specifies whether Lava should exit
// with error when stale exclusions are detected.
ErrorOnStaleExclusions bool `yaml:"errorOnStaleExclusions"`

// Metrics is the file where the metrics will be written.
// If Metrics is an empty string or not specified in the yaml file, then
// the metrics report is not saved.
Expand Down
36 changes: 35 additions & 1 deletion internal/report/human.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
{{- if .Vulns}}
{{template "vulns" . -}}
{{end -}}
{{- if .StaleExcls}}
{{template "staleExcls" . -}}
{{end -}}
{{- end -}}


Expand Down Expand Up @@ -158,10 +161,41 @@ Number of excluded vulnerabilities not included in the summary table: {{.Exclude
{{- $rsc := . -}}
- {{$rsc.Name | bold}}:
{{- range $row := $rsc.Rows}}{{range $i, $header := $rsc.Header}}
{{if eq $i 0}}- {{else}} {{end}}{{ $header | trim | bold}}: {{index $row $header | trim -}}
{{if eq $i 0}}- {{else}} {{end}}{{$header | trim | bold}}: {{index $row $header | trim -}}
{{end}}{{end}}
{{- end -}}

{{- /* staleExcls is the template used to render the details of the stale exclusions. */ -}}
{{- define "staleExcls" -}}
{{"STALE EXCLUSIONS" | bold | underline}}

{{range $excl := .StaleExcls}}
{{- template "excl" . -}}
{{end}}
{{- end -}}

{{- /* excl is the template used to render an exclusion. */ -}}
{{- define "excl" -}}
{{- $pref := "- " -}}
{{- if .Target}}
{{- $pref}}{{"Target" | bold}}: {{.Target | trim}}{{$pref = " "}}
{{end -}}
{{- if .Description}}
{{- $pref}}{{"Description" | bold}}: {{.Description | trim}}{{$pref = " "}}
{{end -}}
{{- if .Resource}}
{{- $pref}}{{"Resource" | bold}}: {{.Resource | trim}}{{$pref = " "}}
{{end -}}
{{- if .Fingerprint}}
{{- $pref}}{{"Fingerprint" | bold}}: {{.Fingerprint | trim}}{{$pref = " "}}
{{end -}}
{{- if .Summary}}
{{- $pref}}{{"Summary" | bold}}: {{.Summary | trim}}{{$pref = " "}}
{{end -}}
{{- if not .ExpirationDate.IsZero}}
{{- $pref}}{{"Expiration Date" | bold}}: {{.ExpirationDate.String | trim}}{{$pref = " "}}
{{end -}}
{{- end -}}

{{- /* Render the report. */ -}}
{{- template "report" . -}}
25 changes: 14 additions & 11 deletions internal/report/humanprinter.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ var (
)

// Print renders the scan results in a human-readable format.
func (prn humanPrinter) Print(w io.Writer, vulns []vulnerability, summ summary, status []checkStatus) error {
func (prn humanPrinter) Print(w io.Writer, vulns []vulnerability, summ summary, status []checkStatus, staleExcls []config.Exclusion) error {
// count the total non-excluded vulnerabilities found.
var total int
for _, ss := range summ.count {
Expand All @@ -53,17 +53,20 @@ func (prn humanPrinter) Print(w io.Writer, vulns []vulnerability, summ summary,
}

data := struct {
Stats map[string]int
Total int
Excluded int
Vulns []vulnerability
Status []checkStatus
Stats map[string]int
Total int
Excluded int
Vulns []vulnerability
Status []checkStatus
AllExclMatched bool
StaleExcls []config.Exclusion
}{
Stats: stats,
Total: total,
Excluded: summ.excluded,
Vulns: vulns,
Status: status,
Stats: stats,
Total: total,
Excluded: summ.excluded,
Vulns: vulns,
Status: status,
StaleExcls: staleExcls,
}

if err := humanTmpl.Execute(w, data); err != nil {
Expand Down
8 changes: 7 additions & 1 deletion internal/report/humanprinter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ func TestUserFriendlyPrinter_Print(t *testing.T) {
vulnerabilities []vulnerability
summ summary
status []checkStatus
staleExcls []config.Exclusion
want []string
}{
{
Expand Down Expand Up @@ -162,13 +163,18 @@ func TestUserFriendlyPrinter_Print(t *testing.T) {
Status: "FINISHED",
},
},
staleExcls: []config.Exclusion{
{Summary: "Unused exclusion"},
},
want: []string{
"STATUS",
"FINISHED",
"SUMMARY",
"Number of excluded vulnerabilities not included in the summary table: 3",
"VULNERABILITIES",
"Vulnerability Summary 1",
"STALE EXCLUSIONS",
"- Summary: Unused exclusion",
},
},
{
Expand All @@ -193,7 +199,7 @@ func TestUserFriendlyPrinter_Print(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
var buf bytes.Buffer
w := humanPrinter{}
if err := w.Print(&buf, tt.vulnerabilities, tt.summ, tt.status); err != nil {
seilagamo marked this conversation as resolved.
Show resolved Hide resolved
if err := w.Print(&buf, tt.vulnerabilities, tt.summ, tt.status, tt.staleExcls); err != nil {
t.Errorf("unexpected error value: %v", err)
}
text := buf.String()
Expand Down
4 changes: 3 additions & 1 deletion internal/report/jsonprinter.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ import (
"encoding/json"
"fmt"
"io"

"github.com/adevinta/lava/internal/config"
)

// jsonPrinter represents a JSON report printer.
type jsonPrinter struct{}

// Print renders the scan results in JSON format.
func (prn jsonPrinter) Print(w io.Writer, vulns []vulnerability, _ summary, _ []checkStatus) error {
func (prn jsonPrinter) Print(w io.Writer, vulns []vulnerability, _ summary, _ []checkStatus, _ []config.Exclusion) error {
enc := json.NewEncoder(w)
enc.SetIndent("", " ")
if err := enc.Encode(vulns); err != nil {
Expand Down
2 changes: 1 addition & 1 deletion internal/report/jsonprinter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ func TestJsonPrinter_Print(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
var buf bytes.Buffer
w := jsonPrinter{}
err := w.Print(&buf, tt.vulnerabilities, summary{}, nil)
err := w.Print(&buf, tt.vulnerabilities, summary{}, nil, nil)
if (err == nil) != tt.wantNilErr {
t.Errorf("unexpected error value: %v", err)
}
Expand Down
Loading
Loading