Skip to content

Commit

Permalink
feat: add CVSS3 scores to report
Browse files Browse the repository at this point in the history
CVSS3 scores are now shown preferentially, only falling back to CVSS2
when a CVSS3 score is not present.
  • Loading branch information
jamestelfer committed Nov 23, 2023
1 parent 3cb048f commit aabc6a0
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 21 deletions.
35 changes: 34 additions & 1 deletion src/finding/summary.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package finding

import (
"net/url"
"regexp"
"slices"
"strings"
"time"
Expand All @@ -26,6 +27,7 @@ type Detail struct {
PackageName string
PackageVersion string
CVSS2 CVSSScore
CVSS3 CVSSScore

Ignore *findingconfig.Ignore
}
Expand Down Expand Up @@ -132,6 +134,9 @@ func findingToDetail(finding types.ImageScanFinding) Detail {
cvss2Vector := findingAttributeValue(finding, "CVSS2_VECTOR")
cvss2VectorURL := cvss2VectorURL(cvss2Vector)

cvss3Vector := findingAttributeValue(finding, "CVSS3_VECTOR")
cvss3Vector, cvss3VectorURL := cvss3VectorURL(cvss3Vector)

return Detail{
Name: name,
URI: uri,
Expand All @@ -144,7 +149,11 @@ func findingToDetail(finding types.ImageScanFinding) Detail {
Vector: cvss2Vector,
VectorURL: cvss2VectorURL,
},
}
CVSS3: CVSSScore{
Score: findingAttributeValue(finding, "CVSS3_SCORE"),
Vector: cvss3Vector,
VectorURL: cvss3VectorURL,
}}
}

func findingAttributeValue(finding types.ImageScanFinding, name string) string {
Expand Down Expand Up @@ -184,3 +193,27 @@ func cvss2VectorURL(cvss2Vector string) string {
}
return cvss2VectorURL
}

// CVSS3 vector have their version at the front: we need to split this out to
// pass to the calculator URL
var cvss3VectorPattern = regexp.MustCompile(`^CVSS:([\d.]+)/(.+)$`)

func cvss3VectorURL(versionedVector string) (string, string) {
vector := versionedVector
vectorURL := ""

if versionedVector != "" {
version := "3.1"

if matches := cvss3VectorPattern.FindStringSubmatch(versionedVector); matches != nil {
version = matches[1]
vector = matches[2]
}

vectorURL = "https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator" +
"?vector=" + url.QueryEscape(vector) +
"&version=" + url.QueryEscape(version)
}

return vector, vectorURL
}
28 changes: 25 additions & 3 deletions src/finding/summary_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,18 +64,19 @@ func TestSummarize(t *testing.T) {
}),
},
{
name: "findings with CVSS2 scores",
name: "findings with CVSS2 and CVSS3 scores",
data: types.ImageScanFindings{
Findings: []types.ImageScanFinding{
fscore("CVE-2019-5188", "HIGH", "1.2", "AV:L/AC:L/Au:N/C:P/I:P/A:P"),
fscore("INVALID-CVE", "CRITICAL", "", ""),
fscore("CVE-2019-5189", "HIGH", "", ""),
fscore("CVE-2019-5189", "HIGH", "6", ""),
fscore3("CVE-2019-5189", "HIGH", "9", "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N"),
},
},
expected: autogold.Expect(finding.Summary{
Counts: map[types.FindingSeverity]finding.SeverityCount{
types.FindingSeverity("CRITICAL"): {Included: 1},
types.FindingSeverity("HIGH"): {Included: 2},
types.FindingSeverity("HIGH"): {Included: 3},
},
Details: []finding.Detail{
{
Expand All @@ -94,6 +95,16 @@ func TestSummarize(t *testing.T) {
{
Name: "CVE-2019-5189",
Severity: types.FindingSeverity("HIGH"),
CVSS2: finding.CVSSScore{Score: "6"},
},
{
Name: "CVE-2019-5189",
Severity: types.FindingSeverity("HIGH"),
CVSS3: finding.CVSSScore{
Score: "9",
Vector: "AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N",
VectorURL: "https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator?vector=AV%3AN%2FAC%3AL%2FPR%3AN%2FUI%3AN%2FS%3AU%2FC%3AH%2FI%3AH%2FA%3AN&version=3.1",
},
},
},
Ignored: []finding.Detail{},
Expand Down Expand Up @@ -208,6 +219,17 @@ func fscore(name string, severity types.FindingSeverity, cvss2 string, vector st
}
}

func fscore3(name string, severity types.FindingSeverity, score string, vector string) types.ImageScanFinding {
return types.ImageScanFinding{
Name: &name,
Severity: severity,
Attributes: []types.Attribute{
{Key: aws.String("CVSS3_SCORE"), Value: &score},
{Key: aws.String("CVSS3_VECTOR"), Value: &vector},
},
}
}

func i(id string) findingconfig.Ignore {
return findingconfig.Ignore{ID: id}
}
21 changes: 14 additions & 7 deletions src/report/annotation.gohtml
Original file line number Diff line number Diff line change
Expand Up @@ -42,27 +42,33 @@ be wrapped in <p> tag by the Markdown renderer in Buildkite.
{{ define "findingName" }}{{ if .Description }}<details><summary>{{ template "findingNameLink" . }}</summary><div>{{ .Description }}</div></details>{{ else }}{{ template "findingNameLink" . }}{{ end }}{{ end }}
{{ define "findingIgnoreUntil" }}{{ if .Until | hasUntilValue }}{{ .Until }}{{ else }}<div class="italic">(indefinitely)</div>{{ end }}{{ end }}
{{ define "findingIgnore"}}{{ if .Reason }}<details><summary>{{ template "findingIgnoreUntil" . }}</summary><div>{{ .Reason }}</div></details>{{ else }}{{ template "findingIgnoreUntil" . }}{{ end }}{{ end }}
{{ define "cvssScore"
}}{{ .Score | nbsp}}{{ if .Vector }} (<a href="{{ .VectorURL }}">{{ .Vector }}</a>){{ end
}}{{ end }}
{{ define "cvssScore" }}{{ .Score | nbsp}}{{ end }}
{{ define "cvssVector" }}{{ if .Vector }}<a href="{{ .VectorURL }}">{{ .Vector }}</a>{{ else }}&nbsp;{{end}}{{ end }}
{{ define "cvssCells" }}
{{ if .CVSS3.Score }}<td>{{ template "cvssScore" .CVSS3 }}</td><td>{{ template "cvssVector" .CVSS3 }}</td>{{
else
}}<td>{{ if .CVSS2.Score }}{{ template "cvssScore" .CVSS2 }} <em>(*CVSS2)</em>{{ end }}</td><td>{{ template "cvssVector" .CVSS2 }}</td>{{ end }}
{{ end }}
{{ if (or .FindingSummary.Details .FindingSummary.Ignored) }}
<details>
<summary>Vulnerability details</summary>
<div>
<p>All listed scores are CVSS3 unless otherwise noted.</p>
{{ if .FindingSummary.Details }}
<table>
<tr>
<th>CVE</th>
<th>Severity</th>
<th>Affects</th>
<th>CVSS2 score (vector)</th>
<th>CVSS score</th>
<th>CVSS vector</th>
</tr>
{{ range $f := .FindingSummary.Details | sortFindings }}
<tr>
<td>{{ template "findingName" . }}</td>
<td>{{ $f.Severity | string | lowerCase | titleCase }}</td>
<td>{{ $f.PackageName | nbsp }} {{ $f.PackageVersion | nbsp }}</td>
<td>{{ template "cvssScore" $f.CVSS2 }}</td>
{{ template "cvssCells" $f }}
</tr>
{{ end }}
</table>
Expand All @@ -77,15 +83,16 @@ be wrapped in <p> tag by the Markdown renderer in Buildkite.
<th>Severity</th>
<th>Ignored until</th>
<th>Affects</th>
<th>CVSS2 score (vector)</th>
<th>CVSS score</th>
<th>CVSS vector</th>
</tr>
{{ range $f := .FindingSummary.Ignored | sortFindings }}
<tr>
<td>{{ template "findingName" . }}</td>
<td>{{ $f.Severity | string | lowerCase | titleCase }}</td>
<td>{{ template "findingIgnore" $f.Ignore }}</td>
<td>{{ $f.PackageName | nbsp }} {{ $f.PackageVersion | nbsp }}</td>
<td>{{ template "cvssScore" $f.CVSS2 }}</td>
{{ template "cvssCells" $f }}
</tr>
{{ end }}
</table>
Expand Down
10 changes: 10 additions & 0 deletions src/report/annotation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ func TestReports(t *testing.T) {
Vector: "AV:L/AC:L/Au:N/C:P/I:P/A:P",
VectorURL: "https://nvd.nist.gov/vuln-metrics/cvss/v2-calculator?vector=%28AV%3AL%2FAC%3AL%2FAu%3AN%2FC%3AP%2FI%3AP%2FA%3AP%29",
},
CVSS3: finding.CVSSScore{
Score: "9",
Vector: "AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N",
VectorURL: "https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator?vector=AV%3AN%2FAC%3AL%2FPR%3AN%2FUI%3AN%2FS%3AU%2FC%3AH%2FI%3AH%2FA%3AN&version=3.1",
},
},
{
Name: "CVE-2019-5200",
Expand Down Expand Up @@ -180,6 +185,11 @@ func TestReports(t *testing.T) {
Score: "10.0",
Vector: "AV:L/AC:L/Au:N/C:P/I:P/A:P",
},
CVSS3: finding.CVSSScore{
Score: "9",
Vector: "AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N",
VectorURL: "https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator?vector=AV%3AN%2FAC%3AL%2FPR%3AN%2FUI%3AN%2FS%3AU%2FC%3AH%2FI%3AH%2FA%3AN&version=3.1",
},
Ignore: &findingconfig.Ignore{
ID: "CVE-2019-5300",
Until: findingconfig.MustParseUntil("2023-12-31"),
Expand Down
18 changes: 14 additions & 4 deletions src/report/testdata/TestReports/findings_included.golden
Original file line number Diff line number Diff line change
Expand Up @@ -45,37 +45,47 @@





<details>
<summary>Vulnerability details</summary>
<div>
<p>All listed scores are CVSS3 unless otherwise noted.</p>

<table>
<tr>
<th>CVE</th>
<th>Severity</th>
<th>Affects</th>
<th>CVSS2 score (vector)</th>
<th>CVSS score</th>
<th>CVSS vector</th>
</tr>

<tr>
<td><details><summary><a href="http://people.ubuntu.com/~ubuntu-security/cve/CVE-2019-5200">CVE-2019-5200</a></summary><div>Another vulnerability.</div></details></td>
<td>Critical</td>
<td>5200-package 5200-version</td>
<td>10.0 (<a href="https://nvd.nist.gov/vuln-metrics/cvss/v2-calculator?vector=%28AV%3AL%2FAC%3AL%2FAu%3AN%2FC%3AP%2FI%3AP%2FA%3AP%29">AV:L/AC:L/Au:N/C:P/I:P/A:P</a>)</td>

<td>10.0 <em>(*CVSS2)</em></td><td><a href="https://nvd.nist.gov/vuln-metrics/cvss/v2-calculator?vector=%28AV%3AL%2FAC%3AL%2FAu%3AN%2FC%3AP%2FI%3AP%2FA%3AP%29">AV:L/AC:L/Au:N/C:P/I:P/A:P</a></td>

</tr>

<tr>
<td><details><summary><a href="http://people.ubuntu.com/~ubuntu-security/cve/CVE-2019-5188">CVE-2019-5188</a></summary><div>A code execution vulnerability exists in the directory rehashing functionality of E2fsprogs e2fsck 1.45.4. A specially crafted ext4 directory can cause an out-of-bounds write on the stack, resulting in code execution. An attacker can corrupt a partition to trigger this vulnerability.</div></details></td>
<td>High</td>
<td>e2fsprogs 1.44.1-1ubuntu1.1</td>
<td>4.6 (<a href="https://nvd.nist.gov/vuln-metrics/cvss/v2-calculator?vector=%28AV%3AL%2FAC%3AL%2FAu%3AN%2FC%3AP%2FI%3AP%2FA%3AP%29">AV:L/AC:L/Au:N/C:P/I:P/A:P</a>)</td>

<td>9</td><td><a href="https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator?vector=AV%3AN%2FAC%3AL%2FPR%3AN%2FUI%3AN%2FS%3AU%2FC%3AH%2FI%3AH%2FA%3AN&amp;version=3.1">AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N</a></td>

</tr>

<tr>
<td><details><summary><a href="http://people.ubuntu.com/~ubuntu-security/cve/CVE-2019-5300">CVE-2019-5300</a></summary><div>Another vulnerability.</div></details></td>
<td>Aa-Bogus-Severity</td>
<td>5300-package 5300-version</td>
<td>10.0 (<a href="https://nvd.nist.gov/vuln-metrics/cvss/v2-calculator?vector=%28AV%3AL%2FAC%3AL%2FAu%3AN%2FC%3AP%2FI%3AP%2FA%3AP%29">AV:L/AC:L/Au:N/C:P/I:P/A:P</a>)</td>

<td>10.0 <em>(*CVSS2)</em></td><td><a href="https://nvd.nist.gov/vuln-metrics/cvss/v2-calculator?vector=%28AV%3AL%2FAC%3AL%2FAu%3AN%2FC%3AP%2FI%3AP%2FA%3AP%29">AV:L/AC:L/Au:N/C:P/I:P/A:P</a></td>

</tr>

</table>
Expand Down
2 changes: 2 additions & 0 deletions src/report/testdata/TestReports/image_label.golden
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@





<p class="p1">
<i>scan completed: <span title="&lt;nil&gt;"></span></i> |
<i>source updated: <span title="&lt;nil&gt;"></span></i>
Expand Down
2 changes: 2 additions & 0 deletions src/report/testdata/TestReports/no_vulnerabilities.golden
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@





<p class="p1">
<i>scan completed: <span title="&lt;nil&gt;"></span></i> |
<i>source updated: <span title="&lt;nil&gt;"></span></i>
Expand Down
25 changes: 19 additions & 6 deletions src/report/testdata/TestReports/some_findings_ignored.golden
Original file line number Diff line number Diff line change
Expand Up @@ -45,30 +45,38 @@





<details>
<summary>Vulnerability details</summary>
<div>
<p>All listed scores are CVSS3 unless otherwise noted.</p>

<table>
<tr>
<th>CVE</th>
<th>Severity</th>
<th>Affects</th>
<th>CVSS2 score (vector)</th>
<th>CVSS score</th>
<th>CVSS vector</th>
</tr>

<tr>
<td><details><summary><a href="http://people.ubuntu.com/~ubuntu-security/cve/CVE-2019-5200">CVE-2019-5200</a></summary><div>Another vulnerability.</div></details></td>
<td>Critical</td>
<td>5200-package 5200-version</td>
<td>10.0 (<a href="https://nvd.nist.gov/vuln-metrics/cvss/v2-calculator?vector=%28AV%3AL%2FAC%3AL%2FAu%3AN%2FC%3AP%2FI%3AP%2FA%3AP%29">AV:L/AC:L/Au:N/C:P/I:P/A:P</a>)</td>

<td>10.0 <em>(*CVSS2)</em></td><td><a href="https://nvd.nist.gov/vuln-metrics/cvss/v2-calculator?vector=%28AV%3AL%2FAC%3AL%2FAu%3AN%2FC%3AP%2FI%3AP%2FA%3AP%29">AV:L/AC:L/Au:N/C:P/I:P/A:P</a></td>

</tr>

<tr>
<td><details><summary><a href="http://people.ubuntu.com/~ubuntu-security/cve/CVE-2019-5188">CVE-2019-5188</a></summary><div>A code execution vulnerability exists in the directory rehashing functionality of E2fsprogs e2fsck 1.45.4. A specially crafted ext4 directory can cause an out-of-bounds write on the stack, resulting in code execution. An attacker can corrupt a partition to trigger this vulnerability.</div></details></td>
<td>High</td>
<td>e2fsprogs 1.44.1-1ubuntu1.1</td>
<td>4.6 (<a href="https://nvd.nist.gov/vuln-metrics/cvss/v2-calculator?vector=%28AV%3AL%2FAC%3AL%2FAu%3AN%2FC%3AP%2FI%3AP%2FA%3AP%29">AV:L/AC:L/Au:N/C:P/I:P/A:P</a>)</td>

<td>4.6 <em>(*CVSS2)</em></td><td><a href="https://nvd.nist.gov/vuln-metrics/cvss/v2-calculator?vector=%28AV%3AL%2FAC%3AL%2FAu%3AN%2FC%3AP%2FI%3AP%2FA%3AP%29">AV:L/AC:L/Au:N/C:P/I:P/A:P</a></td>

</tr>

</table>
Expand All @@ -83,23 +91,28 @@
<th>Severity</th>
<th>Ignored until</th>
<th>Affects</th>
<th>CVSS2 score (vector)</th>
<th>CVSS score</th>
<th>CVSS vector</th>
</tr>

<tr>
<td><details><summary><a href="http://people.ubuntu.com/~ubuntu-security/cve/CVE-2019-5300">CVE-2019-5300</a></summary><div>Another vulnerability.</div></details></td>
<td>Critical</td>
<td><details><summary>2023-12-31</summary><div>Ignored to give the base image a chance to be updated</div></details></td>
<td>5300-package 5300-version</td>
<td>10.0 (<a href="">AV:L/AC:L/Au:N/C:P/I:P/A:P</a>)</td>

<td>9</td><td><a href="https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator?vector=AV%3AN%2FAC%3AL%2FPR%3AN%2FUI%3AN%2FS%3AU%2FC%3AH%2FI%3AH%2FA%3AN&amp;version=3.1">AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N</a></td>

</tr>

<tr>
<td><details><summary><a href="http://people.ubuntu.com/~ubuntu-security/cve/CVE-2023-100">CVE-2023-100</a></summary><div>A vulnerability present in some software but isn&#39;t that bad.</div></details></td>
<td>Low</td>
<td><div class="italic">(indefinitely)</div></td>
<td>100-package 100-version</td>
<td>4.0 (<a href="https://nvd.nist.gov/vuln-metrics/cvss/v2-calculator?vector=%28AV%3AL%2FAC%3AL%2FAu%3AN%2FC%3AP%2FI%3AP%2FA%3AP%29">AV:L/AC:L/Au:N/C:P/I:P/A:P</a>)</td>

<td>4.0 <em>(*CVSS2)</em></td><td><a href="https://nvd.nist.gov/vuln-metrics/cvss/v2-calculator?vector=%28AV%3AL%2FAC%3AL%2FAu%3AN%2FC%3AP%2FI%3AP%2FA%3AP%29">AV:L/AC:L/Au:N/C:P/I:P/A:P</a></td>

</tr>

</table>
Expand Down

0 comments on commit aabc6a0

Please sign in to comment.