-
Notifications
You must be signed in to change notification settings - Fork 0
/
vulnerability.go
141 lines (121 loc) · 3.85 KB
/
vulnerability.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package vulnerability
import (
"strings"
"github.com/google/wire"
"github.com/aquasecurity/trivy-db/pkg/db"
dbTypes "github.com/aquasecurity/trivy-db/pkg/types"
"github.com/aquasecurity/trivy-db/pkg/vulnsrc/vulnerability"
"github.com/zhanglimao/trivy/pkg/log"
"github.com/zhanglimao/trivy/pkg/types"
)
var (
primaryURLPrefixes = map[dbTypes.SourceID][]string{
vulnerability.Debian: {
"http://www.debian.org",
"https://www.debian.org",
},
vulnerability.Ubuntu: {
"http://www.ubuntu.com",
"https://usn.ubuntu.com",
},
vulnerability.RedHat: {"https://access.redhat.com"},
vulnerability.SuseCVRF: {
"http://lists.opensuse.org",
"https://lists.opensuse.org",
},
vulnerability.OracleOVAL: {
"http://linux.oracle.com/errata",
"https://linux.oracle.com/errata",
},
vulnerability.NodejsSecurityWg: {
"https://www.npmjs.com",
"https://hackerone.com",
},
vulnerability.RubySec: {"https://groups.google.com"},
}
)
// SuperSet binds the dependencies
var SuperSet = wire.NewSet(
wire.Struct(new(db.Config)),
wire.Bind(new(db.Operation), new(db.Config)),
NewClient,
)
// Client manipulates vulnerabilities
type Client struct {
dbc db.Operation
}
// NewClient is the factory method for Client
func NewClient(dbc db.Operation) Client {
return Client{dbc: dbc}
}
// FillInfo fills extra info in vulnerability objects
func (c Client) FillInfo(vulns []types.DetectedVulnerability) {
for i := range vulns {
vulnID := vulns[i].VulnerabilityID
vuln, err := c.dbc.GetVulnerability(vulnID)
if err != nil {
log.Logger.Warnf("Error while getting vulnerability details: %s", err)
continue
}
// Detect the data source
var source dbTypes.SourceID
if vulns[i].DataSource != nil {
source = vulns[i].DataSource.ID
}
// Select the severity according to the detected source.
severity, severitySource := c.getVendorSeverity(vulnID, &vuln, source)
// The vendor might provide package-specific severity like Debian.
// For example, CVE-2015-2328 in Debian has "unimportant" for mongodb and "low" for pcre3.
// In that case, we keep the severity as is.
if vulns[i].SeveritySource != "" {
severity = vulns[i].Severity
severitySource = vulns[i].SeveritySource
}
// Add the vulnerability detail
vulns[i].Vulnerability = vuln
vulns[i].Severity = severity
vulns[i].SeveritySource = severitySource
vulns[i].PrimaryURL = c.getPrimaryURL(vulnID, vuln.References, source)
}
}
func (c Client) getVendorSeverity(vulnID string, vuln *dbTypes.Vulnerability, source dbTypes.SourceID) (string, dbTypes.SourceID) {
if vs, ok := vuln.VendorSeverity[source]; ok {
return vs.String(), source
}
// use severity from GitHub for all GHSA-xxx vulnerabilities
// govuln doesn't have severity. Use severity from GitHub(for CVE-xxx vulns)
if strings.HasPrefix(vulnID, "GHSA-") || source == vulnerability.GoVulnDB {
if vs, ok := vuln.VendorSeverity[vulnerability.GHSA]; ok {
return vs.String(), vulnerability.GHSA
}
}
// Try NVD as a fallback if it exists
if vs, ok := vuln.VendorSeverity[vulnerability.NVD]; ok {
return vs.String(), vulnerability.NVD
}
if vuln.Severity == "" {
return dbTypes.SeverityUnknown.String(), ""
}
return vuln.Severity, ""
}
func (c Client) getPrimaryURL(vulnID string, refs []string, source dbTypes.SourceID) string {
switch {
case strings.HasPrefix(vulnID, "CVE-"):
return "https://avd.aquasec.com/nvd/" + strings.ToLower(vulnID)
case strings.HasPrefix(vulnID, "RUSTSEC-"):
return "https://osv.dev/vulnerability/" + vulnID
case strings.HasPrefix(vulnID, "GHSA-"):
return "https://github.com/advisories/" + vulnID
case strings.HasPrefix(vulnID, "TEMP-"):
return "https://security-tracker.debian.org/tracker/" + vulnID
}
prefixes := primaryURLPrefixes[source]
for _, pre := range prefixes {
for _, ref := range refs {
if strings.HasPrefix(ref, pre) {
return ref
}
}
}
return ""
}