Skip to content

Commit dfe757e

Browse files
refactor: add warning if severity not from vendor (or NVD or GH) is used (#6726)
Signed-off-by: knqyf263 <[email protected]> Co-authored-by: Teppei Fukuda <[email protected]>
1 parent f144e91 commit dfe757e

File tree

2 files changed

+54
-11
lines changed

2 files changed

+54
-11
lines changed

docs/docs/scanner/vulnerability.md

+38-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,44 @@ If the data source does not provide a severity, the severity is determined based
6666
| 7.0-8.9 | High |
6767
| 9.0-10.0 | Critical |
6868

69-
If the CVSS score is also not provided, it falls back to [NVD][nvd], and if NVD does not have severity, it will be UNKNOWN.
69+
If the CVSS score is also not provided, it falls back to [NVD][nvd].
70+
71+
NVD and some vendors may delay severity analysis, while other vendors, such as Red Hat, are able to quickly evaluate and announce the severity of vulnerabilities.
72+
To avoid marking too many vulnerabilities as "UNKNOWN" severity, Trivy uses severity ratings from other vendors when the NVD information is not yet available.
73+
The order of preference for vendor severity data can be found [here](https://github.com/aquasecurity/trivy-db/blob/79d0fbd1e246f3c77eef4b9826fe4bf65940b221/pkg/vulnsrc/vulnerability/vulnerability.go#L17-L19).
74+
75+
You can reference `SeveritySource` in the [JSON reporting format](../configuration/reporting.md#json) to see from where the severity is taken for a given vulnerability.
76+
77+
```shell
78+
"SeveritySource": "debian",
79+
```
80+
81+
82+
In addition, you can see all the vendor severity ratings.
83+
84+
```json
85+
"VendorSeverity": {
86+
"amazon": 2,
87+
"cbl-mariner": 4,
88+
"ghsa": 4,
89+
"nvd": 4,
90+
"photon": 4,
91+
"redhat": 2,
92+
"ubuntu": 2
93+
}
94+
```
95+
96+
Here is the severity mapping in Trivy:
97+
98+
| Number | Severity |
99+
|:------:|----------|
100+
| 0 | Unknown |
101+
| 1 | Low |
102+
| 2 | Medium |
103+
| 3 | High |
104+
| 4 | Critical |
105+
106+
If no vendor has a severity, the `UNKNOWN` severity will be used.
70107

71108
### Unfixed Vulnerabilities
72109
The unfixed/unfixable vulnerabilities mean that the patch has not yet been provided on their distribution.

pkg/vulnerability/vulnerability.go

+16-10
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ package vulnerability
22

33
import (
44
"strings"
5+
"sync"
56

67
"github.com/google/wire"
8+
"github.com/samber/lo"
79

810
"github.com/aquasecurity/trivy-db/pkg/db"
911
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
@@ -46,6 +48,12 @@ var SuperSet = wire.NewSet(
4648
NewClient,
4749
)
4850

51+
// Show warning if we use severity from another vendor
52+
// cf. https://github.com/aquasecurity/trivy/issues/6714
53+
var onceWarn = sync.OnceFunc(func() {
54+
log.Warn("Using severities from other vendors for some vulnerabilities. Read https://aquasecurity.github.io/trivy/latest/docs/scanner/vulnerability/#severity-selection for details.")
55+
})
56+
4957
// Client manipulates vulnerabilities
5058
type Client struct {
5159
dbc db.Operation
@@ -77,13 +85,10 @@ func (c Client) FillInfo(vulns []types.DetectedVulnerability) {
7785
}
7886

7987
// Detect the data source
80-
var source dbTypes.SourceID
81-
if vulns[i].DataSource != nil {
82-
source = vulns[i].DataSource.ID
83-
}
88+
dataSource := lo.FromPtr(vulns[i].DataSource)
8489

85-
// Select the severity according to the detected source.
86-
severity, severitySource := c.getVendorSeverity(vulnID, &vuln, source)
90+
// Select the severity according to the detected sourceID.
91+
severity, severitySource := c.getVendorSeverity(vulnID, &vuln, dataSource)
8792

8893
// The vendor might provide package-specific severity like Debian.
8994
// For example, CVE-2015-2328 in Debian has "unimportant" for mongodb and "low" for pcre3.
@@ -105,13 +110,13 @@ func (c Client) FillInfo(vulns []types.DetectedVulnerability) {
105110

106111
vulns[i].Severity = severity
107112
vulns[i].SeveritySource = severitySource
108-
vulns[i].PrimaryURL = c.getPrimaryURL(vulnID, vuln.References, source)
113+
vulns[i].PrimaryURL = c.getPrimaryURL(vulnID, vuln.References, dataSource.ID)
109114
}
110115
}
111116

112-
func (c Client) getVendorSeverity(vulnID string, vuln *dbTypes.Vulnerability, source dbTypes.SourceID) (string, dbTypes.SourceID) {
113-
if vs, ok := vuln.VendorSeverity[source]; ok {
114-
return vs.String(), source
117+
func (c Client) getVendorSeverity(vulnID string, vuln *dbTypes.Vulnerability, dataSource dbTypes.DataSource) (string, dbTypes.SourceID) {
118+
if vs, ok := vuln.VendorSeverity[dataSource.ID]; ok {
119+
return vs.String(), dataSource.ID
115120
}
116121

117122
// use severity from GitHub for all GHSA-xxx vulnerabilities
@@ -130,6 +135,7 @@ func (c Client) getVendorSeverity(vulnID string, vuln *dbTypes.Vulnerability, so
130135
return dbTypes.SeverityUnknown.String(), ""
131136
}
132137

138+
onceWarn()
133139
return vuln.Severity, ""
134140
}
135141

0 commit comments

Comments
 (0)