Skip to content

Commit 7c2244f

Browse files
committed
cmd/vulnreport: auto-populate cve_metadata for first-party reports
For first-party reports where we have assigned our own CVE, auto-populate "cve_metadata" instead of "cves". Change-Id: Ifa23ece087f03a294e07ba4fba4267a0de890431 Reviewed-on: https://go-review.googlesource.com/c/vulndb/+/596179 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Damien Neil <[email protected]>
1 parent 6155dc5 commit 7c2244f

File tree

3 files changed

+53
-26
lines changed

3 files changed

+53
-26
lines changed

cmd/vulnreport/creator.go

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -105,13 +105,22 @@ func (c *creator) reportFromIssue(ctx context.Context, iss *issues.Issue) error
105105
modulePath: modulePath(iss),
106106
aliases: aliases(iss),
107107
reviewStatus: reviewStatusOf(iss, c.reviewStatus),
108+
originalCVE: originalCVE(iss),
108109
})
109110
if err != nil {
110111
return err
111112
}
112113
return c.write(ctx, r)
113114
}
114115

116+
func originalCVE(iss *issues.Issue) string {
117+
aliases := aliases(iss)
118+
if iss.HasLabel(labelFirstParty) && len(aliases) == 1 && idstr.IsCVE(aliases[0]) {
119+
return aliases[0]
120+
}
121+
return ""
122+
}
123+
115124
func reviewStatusOf(iss *issues.Issue, reviewStatus report.ReviewStatus) report.ReviewStatus {
116125
d := defaultReviewStatus(iss)
117126
// If a valid review status is provided, it overrides the priority label.
@@ -134,25 +143,33 @@ func defaultReviewStatus(iss *issues.Issue) report.ReviewStatus {
134143
return report.Unreviewed
135144
}
136145

146+
func (c *creator) metaToSource(ctx context.Context, meta *reportMeta) report.Source {
147+
if cveID := meta.originalCVE; cveID != "" {
148+
log.Infof("%s: creating original report for Go-CNA-assigned %s", meta.id, cveID)
149+
return report.OriginalCVE(cveID)
150+
}
151+
152+
if src := c.sourceFromBestAlias(ctx, meta.aliases, *preferCVE); src != nil {
153+
log.Infof("%s: picked %s as best source alias (from [%s])", meta.id, src.SourceID(),
154+
strings.Join(meta.aliases, ", "))
155+
return src
156+
}
157+
158+
log.Infof("%s: no suitable alias found, creating basic report", meta.id)
159+
return report.Original()
160+
}
161+
137162
func (c *creator) reportFromMeta(ctx context.Context, meta *reportMeta) (*yamlReport, error) {
138163
// Find the underlying module if the "module" provided is actually a package path.
139164
if module, err := c.pc.FindModule(meta.modulePath); err == nil { // no error
140165
meta.modulePath = module
141166
}
167+
meta.aliases = c.allAliases(ctx, meta.aliases)
142168

143-
var src report.Source
144-
aliases := c.allAliases(ctx, meta.aliases)
145-
src, ok := c.sourceFromBestAlias(ctx, aliases, *preferCVE)
146-
if ok {
147-
log.Infof("%s: picked %s as best source alias (from [%s])", meta.id, src.SourceID(), strings.Join(aliases, ", "))
148-
} else {
149-
log.Infof("%s: no suitable alias found, creating basic report", meta.id)
150-
}
151-
152-
raw := report.New(src, c.pc,
169+
raw := report.New(c.metaToSource(ctx, meta), c.pc,
153170
report.WithGoID(meta.id),
154171
report.WithModulePath(meta.modulePath),
155-
report.WithAliases(aliases),
172+
report.WithAliases(meta.aliases),
156173
report.WithReviewStatus(meta.reviewStatus),
157174
report.WithUnexcluded(meta.unexcluded),
158175
)
@@ -296,6 +313,7 @@ type reportMeta struct {
296313
aliases []string
297314
excluded, unexcluded report.ExcludedReason
298315
reviewStatus report.ReviewStatus
316+
originalCVE string
299317
}
300318

301319
const todo = "TODO: "
@@ -348,9 +366,12 @@ func addTODOs(r *yamlReport) {
348366
if len(r.Credits) == 0 {
349367
r.Credits = []string{todo + "who discovered/reported this vulnerability (optional)"}
350368
}
351-
if len(r.CVEs) == 0 {
369+
if r.CVEMetadata == nil && len(r.CVEs) == 0 {
352370
r.CVEs = []string{todo + "CVE id(s) for this vulnerability"}
353371
}
372+
if r.CVEMetadata != nil && r.CVEMetadata.CWE == "" {
373+
r.CVEMetadata.CWE = todo + "CWE ID"
374+
}
354375
addReferenceTODOs(r)
355376
}
356377

cmd/vulnreport/find_aliases.go

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -124,36 +124,31 @@ func aliasesForCVE(ctx context.Context, cve string, gc ghsaClient) (aliases []st
124124
// By default, it prefers the first GHSA in the list, followed by the first CVE in the list
125125
// (if no GHSA is present).
126126
// If "preferCVE" is true, it prefers CVEs instead.
127-
func (af *aliasFinder) sourceFromBestAlias(ctx context.Context, aliases []string, preferCVE bool) (report.Source, bool) {
127+
func (af *aliasFinder) sourceFromBestAlias(ctx context.Context, aliases []string, preferCVE bool) report.Source {
128128
firstChoice := idstr.IsGHSA
129129
secondChoice := idstr.IsCVE
130130
if preferCVE {
131131
firstChoice, secondChoice = secondChoice, firstChoice
132132
}
133133

134-
find := func(f func(string) bool) (report.Source, bool) {
134+
find := func(f func(string) bool) report.Source {
135135
for _, alias := range aliases {
136136
if f(alias) {
137137
src, err := af.fetch(ctx, alias)
138138
if err != nil {
139139
log.Warnf("could not fetch record for preferred alias %s: %v", alias, err)
140140
continue
141141
}
142-
return src, true
142+
return src
143143
}
144144
}
145-
return nil, false
145+
return nil
146146
}
147147

148-
if src, found := find(firstChoice); found {
149-
return src, true
148+
if src := find(firstChoice); src != nil {
149+
return src
150150
}
151-
152-
if src, found := find(secondChoice); found {
153-
return src, true
154-
}
155-
156-
return report.Original(), false
151+
return find(secondChoice)
157152
}
158153

159154
func (a *aliasFinder) fetch(ctx context.Context, alias string) (report.Source, error) {

internal/report/new.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,21 +136,32 @@ func newCfg(opts []NewOption) *cfg {
136136
//
137137
// This is used for standard library & toolchain reports, or in cases where the
138138
// source report cannot be retrieved automatically.
139-
type original struct{}
139+
type original struct {
140+
cveID string // the Go-CNA-assigned CVE for this report, if applicable
141+
}
140142

141143
var _ Source = &original{}
142144

143145
func Original() Source {
144146
return &original{}
145147
}
146148

147-
func (original) ToReport(modulePath string) *Report {
149+
func OriginalCVE(cveID string) Source {
150+
return &original{cveID: cveID}
151+
}
152+
153+
func (o *original) ToReport(modulePath string) *Report {
154+
var cveMeta *CVEMeta
155+
if o.cveID != "" {
156+
cveMeta = &CVEMeta{ID: o.cveID}
157+
}
148158
return &Report{
149159
Modules: []*Module{
150160
{
151161
Module: modulePath,
152162
},
153163
},
164+
CVEMetadata: cveMeta,
154165
}
155166
}
156167

0 commit comments

Comments
 (0)