Skip to content

Commit 319ae10

Browse files
feat(db): populate vulnerability information with published & modified dates from GHSA (OSV) if NVD dates are not present (#527)
Co-authored-by: DmitriyLewen <dmitriy.lewen@smartforce.io>
1 parent ea3c2ba commit 319ae10

9 files changed

Lines changed: 159 additions & 50 deletions

File tree

pkg/types/types.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ type VulnerabilityDetail struct {
8181
References []string `json:",omitempty"`
8282
Title string `json:",omitempty"`
8383
Description string `json:",omitempty"`
84-
PublishedDate *time.Time `json:",omitempty"` // Take from NVD
85-
LastModifiedDate *time.Time `json:",omitempty"` // Take from NVD
84+
PublishedDate *time.Time `json:",omitempty"` // Take from NVD or GHSA
85+
LastModifiedDate *time.Time `json:",omitempty"` // Take from NVD or GHSA
8686
}
8787

8888
type AdvisoryDetail struct {

pkg/vulndb/db.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ func (t TrivyDB) optimize() error {
147147
return nil
148148
}
149149

150-
vuln := t.vulnClient.Normalize(details)
150+
vuln := t.vulnClient.Normalize(cveID, details)
151151
if err := t.dbc.PutVulnerability(tx, cveID, vuln); err != nil {
152152
return eb.Wrapf(err, "failed to put vulnerability")
153153
}

pkg/vulnsrc/aqua/aqua_test.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"testing"
66

77
"github.com/aquasecurity/trivy-db/pkg/types"
8+
"github.com/aquasecurity/trivy-db/pkg/utils"
89
"github.com/aquasecurity/trivy-db/pkg/vulnsrc/aqua"
910
"github.com/aquasecurity/trivy-db/pkg/vulnsrc/vulnerability"
1011
"github.com/aquasecurity/trivy-db/pkg/vulnsrctest"
@@ -64,8 +65,10 @@ func TestVulnSrc_Update(t *testing.T) {
6465
"https://github.com/ultralytics/ultralytics/issues/18027",
6566
"https://github.com/ultralytics/ultralytics/issues/18030",
6667
},
67-
CvssScoreV3: 9.8,
68-
CvssVectorV3: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
68+
CvssScoreV3: 9.8,
69+
CvssVectorV3: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
70+
LastModifiedDate: utils.MustTimeParse("2024-12-18T12:00:00Z"),
71+
PublishedDate: utils.MustTimeParse("2024-12-18T12:00:00Z"),
6972
},
7073
},
7174
{

pkg/vulnsrc/ghsa/ghsa_test.go

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"testing"
66

77
"github.com/aquasecurity/trivy-db/pkg/types"
8+
"github.com/aquasecurity/trivy-db/pkg/utils"
89
"github.com/aquasecurity/trivy-db/pkg/vulnsrc/ghsa"
910
"github.com/aquasecurity/trivy-db/pkg/vulnsrc/vulnerability"
1011
"github.com/aquasecurity/trivy-db/pkg/vulnsrctest"
@@ -62,9 +63,11 @@ func TestVulnSrc_Update(t *testing.T) {
6263
"https://github.com/advisories/GHSA-xx65-cc7g-9pfp",
6364
"https://pivotal.io/security/cve-2018-1196",
6465
},
65-
Severity: types.SeverityMedium,
66-
CvssVectorV3: "CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:H/A:N",
67-
CvssScoreV3: 5.9,
66+
Severity: types.SeverityMedium,
67+
CvssVectorV3: "CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:H/A:N",
68+
CvssScoreV3: 5.9,
69+
LastModifiedDate: utils.MustTimeParse("2021-09-22T18:26:44Z"),
70+
PublishedDate: utils.MustTimeParse("2018-10-18T18:05:57Z"),
6871
},
6972
},
7073
{
@@ -128,9 +131,11 @@ func TestVulnSrc_Update(t *testing.T) {
128131
"https://github.com/FCncdn/MybatisPlusTenantPluginSQLInjection-POC/blob/master/Readme.en.md",
129132
"https://github.com/baomidou/mybatis-plus",
130133
},
131-
Severity: types.SeverityCritical,
132-
CvssVectorV3: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
133-
CvssScoreV3: 9.8,
134+
Severity: types.SeverityCritical,
135+
CvssVectorV3: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
136+
CvssScoreV3: 9.8,
137+
LastModifiedDate: utils.MustTimeParse("2023-04-14T20:31:15Z"),
138+
PublishedDate: utils.MustTimeParse("2023-04-05T15:30:24Z"),
134139
},
135140
},
136141
{
@@ -181,9 +186,11 @@ func TestVulnSrc_Update(t *testing.T) {
181186
"https://github.com/bodil/sized-chunks",
182187
"https://rustsec.org/advisories/RUSTSEC-2020-0041.html",
183188
},
184-
Severity: types.SeverityHigh,
185-
CvssVectorV3: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
186-
CvssScoreV3: 7.5,
189+
Severity: types.SeverityHigh,
190+
CvssVectorV3: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
191+
CvssScoreV3: 7.5,
192+
LastModifiedDate: utils.MustTimeParse("2022-06-14T20:54:51Z"),
193+
PublishedDate: utils.MustTimeParse("2021-08-25T20:46:06Z"),
187194
},
188195
},
189196
{
@@ -240,9 +247,11 @@ func TestVulnSrc_Update(t *testing.T) {
240247
"https://github.com/sophieschmieg/exploits/tree/master/aws_s3_crypto_poc",
241248
"https://pkg.go.dev/vuln/GO-2022-0646",
242249
},
243-
Severity: types.SeverityMedium,
244-
CvssVectorV3: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H/E:P/RL:O/RC:C",
245-
CvssScoreV3: 8.8,
250+
Severity: types.SeverityMedium,
251+
CvssVectorV3: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H/E:P/RL:O/RC:C",
252+
CvssScoreV3: 8.8,
253+
LastModifiedDate: utils.MustTimeParse("2023-02-07T21:27:07Z"),
254+
PublishedDate: utils.MustTimeParse("2022-02-11T23:26:26Z"),
246255
},
247256
},
248257
{
@@ -358,9 +367,11 @@ func TestVulnSrc_Update(t *testing.T) {
358367
"https://github.com/apple/swift-nio/commit/a16e2f54a25b2af217044e5168997009a505930f",
359368
"https://github.com/apple/swift-nio",
360369
},
361-
Severity: types.SeverityMedium,
362-
CvssVectorV3: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N",
363-
CvssScoreV3: 5.3,
370+
Severity: types.SeverityMedium,
371+
CvssVectorV3: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N",
372+
CvssScoreV3: 5.3,
373+
LastModifiedDate: utils.MustTimeParse("2023-06-07T16:01:53Z"),
374+
PublishedDate: utils.MustTimeParse("2023-06-07T16:01:53Z"),
364375
},
365376
},
366377
{

pkg/vulnsrc/k8svulndb/k8svulndb_test.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"testing"
66

77
"github.com/aquasecurity/trivy-db/pkg/types"
8+
"github.com/aquasecurity/trivy-db/pkg/utils"
89
"github.com/aquasecurity/trivy-db/pkg/vulnsrc/k8svulndb"
910
"github.com/aquasecurity/trivy-db/pkg/vulnsrc/vulnerability"
1011
"github.com/aquasecurity/trivy-db/pkg/vulnsrctest"
@@ -40,11 +41,13 @@ func TestVulnSrc_Update(t *testing.T) {
4041
string(vulnerability.Kubernetes),
4142
},
4243
Value: types.VulnerabilityDetail{
43-
Title: "Bypassing policies imposed by the ImagePolicyWebhook and bypassing mountable secrets policy imposed by the ServiceAccount admission plugin",
44-
Description: "Users may be able to launch containers using images that are restricted by ImagePolicyWebhook when using ephemeral containers. Kubernetes clusters are only affected if the ImagePolicyWebhook admission plugin is used together with ephemeral containers.",
45-
References: []string{"https: //www.cve.org/cverecord?id=CVE-2023-2727"},
46-
CvssVectorV3: "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:N",
47-
CvssScoreV3: 6.5,
44+
Title: "Bypassing policies imposed by the ImagePolicyWebhook and bypassing mountable secrets policy imposed by the ServiceAccount admission plugin",
45+
Description: "Users may be able to launch containers using images that are restricted by ImagePolicyWebhook when using ephemeral containers. Kubernetes clusters are only affected if the ImagePolicyWebhook admission plugin is used together with ephemeral containers.",
46+
References: []string{"https: //www.cve.org/cverecord?id=CVE-2023-2727"},
47+
CvssVectorV3: "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:N",
48+
CvssScoreV3: 6.5,
49+
LastModifiedDate: utils.MustTimeParse("2023-06-13T14:42:06Z"),
50+
PublishedDate: utils.MustTimeParse("2023-06-13T14:42:06Z"),
4851
},
4952
},
5053
},

pkg/vulnsrc/osv/osv.go

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ type Advisory struct {
4242
References []string
4343
CVSSScoreV3 float64
4444
CVSSVectorV3 string
45+
Modified time.Time
46+
Published time.Time
4547

4648
// From affected[].database_specific
4749
DatabaseSpecific json.RawMessage
@@ -180,12 +182,14 @@ func (o OSV) commit(tx *bolt.Tx, entry Entry) error {
180182

181183
// Store vulnerability details
182184
vuln := types.VulnerabilityDetail{
183-
Severity: adv.Severity,
184-
References: adv.References,
185-
Title: adv.Title,
186-
Description: adv.Description,
187-
CvssScoreV3: adv.CVSSScoreV3,
188-
CvssVectorV3: adv.CVSSVectorV3,
185+
Severity: adv.Severity,
186+
References: adv.References,
187+
Title: adv.Title,
188+
Description: adv.Description,
189+
CvssScoreV3: adv.CVSSScoreV3,
190+
CvssVectorV3: adv.CVSSVectorV3,
191+
PublishedDate: lo.Ternary(!adv.Published.IsZero(), &adv.Published, nil),
192+
LastModifiedDate: lo.Ternary(!adv.Modified.IsZero(), &adv.Modified, nil),
189193
}
190194

191195
if err = o.dbc.PutVulnerabilityDetail(tx, adv.VulnerabilityID, o.sourceID, vuln); err != nil {
@@ -253,6 +257,8 @@ func (o OSV) parseAffected(entry Entry, vulnIDs, aliases, references []string) (
253257
References: references,
254258
CVSSVectorV3: cvssVectorV3,
255259
CVSSScoreV3: cvssScoreV3,
260+
Modified: entry.Modified,
261+
Published: entry.Published,
256262
DatabaseSpecific: affected.DatabaseSpecific,
257263
}
258264
}

pkg/vulnsrc/osv/osv_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"testing"
66

77
"github.com/aquasecurity/trivy-db/pkg/types"
8+
"github.com/aquasecurity/trivy-db/pkg/utils"
89
"github.com/aquasecurity/trivy-db/pkg/vulnsrc/osv"
910
"github.com/aquasecurity/trivy-db/pkg/vulnsrc/vulnerability"
1011
"github.com/aquasecurity/trivy-db/pkg/vulnsrctest"
@@ -63,6 +64,8 @@ func TestVulnSrc_Update(t *testing.T) {
6364
"http://www.openwall.com/lists/oss-security/2018/07/11/7",
6465
"https://github.com/advisories/GHSA-wgmx-52ph-qqcw",
6566
},
67+
LastModifiedDate: utils.MustTimeParse("2021-06-10T06:51:37.378319Z"),
68+
PublishedDate: utils.MustTimeParse("2018-07-12T12:29:00Z"),
6669
},
6770
},
6871
{

pkg/vulnsrc/vulnerability/vulnerability.go

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package vulnerability
33
import (
44
"sort"
55
"strings"
6+
"time"
67

78
"github.com/aquasecurity/trivy-db/pkg/db"
89
"github.com/aquasecurity/trivy-db/pkg/log"
@@ -36,7 +37,7 @@ func (Vulnerability) IsRejected(details map[types.SourceID]types.VulnerabilityDe
3637
return getRejectedStatus(details)
3738
}
3839

39-
func (Vulnerability) Normalize(details map[types.SourceID]types.VulnerabilityDetail) types.Vulnerability {
40+
func (Vulnerability) Normalize(vulnID string, details map[types.SourceID]types.VulnerabilityDetail) types.Vulnerability {
4041
return types.Vulnerability{
4142
Title: getTitle(details),
4243
Description: getDescription(details),
@@ -45,8 +46,8 @@ func (Vulnerability) Normalize(details map[types.SourceID]types.VulnerabilityDet
4546
VendorSeverity: getVendorSeverity(details),
4647
CVSS: getCVSS(details),
4748
References: getReferences(details),
48-
PublishedDate: details[NVD].PublishedDate,
49-
LastModifiedDate: details[NVD].LastModifiedDate,
49+
PublishedDate: getPublishedDate(vulnID, details),
50+
LastModifiedDate: getLastModifiedDate(vulnID, details),
5051
}
5152
}
5253

@@ -179,6 +180,36 @@ func getReferences(details map[types.SourceID]types.VulnerabilityDetail) []strin
179180
return refs
180181
}
181182

183+
func getPublishedDate(vulnID string, details map[types.SourceID]types.VulnerabilityDetail) *time.Time {
184+
// We should take PublishedData from
185+
// - NVD - for CVE-IDs
186+
// - GHSA - for GHSA-IDs
187+
// cf. https://github.com/aquasecurity/trivy-db/issues/522
188+
switch {
189+
case strings.HasPrefix(vulnID, "CVE-"):
190+
return details[NVD].PublishedDate
191+
case strings.HasPrefix(vulnID, "GHSA-"):
192+
return details[GHSA].PublishedDate
193+
}
194+
195+
return nil
196+
}
197+
198+
func getLastModifiedDate(vulnID string, details map[types.SourceID]types.VulnerabilityDetail) *time.Time {
199+
// We should take LastModifiedDate from
200+
// - NVD - for CVE-IDs
201+
// - GHSA - for GHSA-IDs
202+
// cf. https://github.com/aquasecurity/trivy-db/issues/522
203+
switch {
204+
case strings.HasPrefix(vulnID, "CVE-"):
205+
return details[NVD].LastModifiedDate
206+
case strings.HasPrefix(vulnID, "GHSA-"):
207+
return details[GHSA].LastModifiedDate
208+
}
209+
210+
return nil
211+
}
212+
182213
func getRejectedStatus(details map[types.SourceID]types.VulnerabilityDetail) bool {
183214
for _, source := range AllSourceIDs {
184215
d, ok := details[source]

0 commit comments

Comments
 (0)