Skip to content

Commit 66107ed

Browse files
all: switch to the new shared vuln schema
Change-Id: Ibbbf153cc8078884bf9ac5a3a8b01a75894abb17 Reviewed-on: https://team-review.git.corp.google.com/c/golang/vulndb/+/1055915 Reviewed-by: Roland Shoemaker <bracewell@google.com>
1 parent 3cd20f4 commit 66107ed

File tree

103 files changed

+307
-106
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

103 files changed

+307
-106
lines changed

client/client.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ func (hs *httpSource) Get(packages []string) ([]*osv.Entry, error) {
141141
} else if len(cached) != 0 {
142142
var stale bool
143143
for _, c := range cached {
144-
if c.LastModified.Before(lastModified) {
144+
if c.Modified.Before(lastModified) {
145145
stale = true
146146
break
147147
}

client/client_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,9 @@ func cachedTestVuln2(dbName string) func() Cache {
5454
return func() Cache {
5555
c := &fsCache{}
5656
e := &osv.Entry{
57-
ID: "ID2",
58-
Summary: "cached",
59-
LastModified: time.Now(),
57+
ID: "ID2",
58+
Details: "cached",
59+
Modified: time.Now(),
6060
}
6161
c.WriteEntries(dbName, "golang.org/example/two", []*osv.Entry{e})
6262
return c
@@ -138,8 +138,8 @@ func TestClient(t *testing.T) {
138138
}
139139

140140
for _, v := range vulns {
141-
if s, ok := test.summaries[v.ID]; !ok || v.Summary != s {
142-
t.Errorf("want '%s' summary for vuln with id %v in %s; got '%s'", s, v.ID, test.name, v.Summary)
141+
if s, ok := test.summaries[v.ID]; !ok || v.Details != s {
142+
t.Errorf("want '%s' summary for vuln with id %v in %s; got '%s'", s, v.ID, test.name, v.Details)
143143
}
144144
}
145145
}

cmd/gendb/main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ func main() {
9191
fail(fmt.Sprintf("failed to write %q: %s", outPath+".json", err))
9292
}
9393
for _, v := range vulns {
94-
if v.LastModified.After(index[path]) {
95-
index[path] = v.LastModified
94+
if v.Modified.After(index[path]) {
95+
index[path] = v.Modified
9696
}
9797
}
9898
}

osv/json.go

Lines changed: 43 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -18,28 +18,10 @@ import (
1818
// vulndb implementatiion detail.
1919
type DBIndex map[string]time.Time
2020

21-
type Severity int
21+
type AffectsRangeType int
2222

2323
const (
24-
SevNone Severity = iota
25-
SevLow
26-
SevMedium
27-
SevHigh
28-
SevCritical
29-
)
30-
31-
var strToSev = map[string]Severity{
32-
// "": SevNone,
33-
"low": SevLow,
34-
"medium": SevMedium,
35-
"high": SevHigh,
36-
"critical": SevCritical,
37-
}
38-
39-
type Type int
40-
41-
const (
42-
TypeUnspecified Type = iota
24+
TypeUnspecified AffectsRangeType = iota
4325
TypeGit
4426
TypeSemver
4527
)
@@ -54,7 +36,7 @@ type Package struct {
5436
}
5537

5638
type AffectsRange struct {
57-
Type Type
39+
Type AffectsRangeType
5840
Introduced string
5941
Fixed string
6042
}
@@ -113,59 +95,66 @@ type GoSpecific struct {
11395
URL string
11496
}
11597

98+
type Reference struct {
99+
Type string
100+
URL string
101+
}
102+
116103
// Entry represents a OSV style JSON vulnerability database
117104
// entry
118105
type Entry struct {
119-
ID string
120-
Package Package
121-
Summary string
122-
Details string
123-
Severity Severity
124-
Affects Affects
125-
ReferenceURLs []string `json:"reference_urls,omitempty"`
126-
Aliases []string `json:",omitempty"`
127-
EcosystemSpecific GoSpecific `json:"ecosystem_specific,omitempty"`
128-
LastModified time.Time `json:"last_modified"`
106+
ID string
107+
Published time.Time
108+
Modified time.Time
109+
Withdrawn *time.Time
110+
Aliases []string `json:",omitempty"`
111+
Package Package
112+
Details string
113+
Affects Affects
114+
References []Reference `json:",omitempty"`
115+
Extra struct {
116+
Go GoSpecific
117+
}
129118
}
130119

131120
func Generate(id string, url string, r report.Report) []Entry {
132121
importPath := r.Module
133122
if r.Package != "" {
134123
importPath = r.Package
135124
}
125+
lastModified := r.Published
126+
if r.LastModified != nil {
127+
lastModified = *r.LastModified
128+
}
136129
entry := Entry{
137-
ID: id,
130+
ID: id,
131+
Published: r.Published,
132+
Modified: lastModified,
133+
Withdrawn: r.Withdrawn,
138134
Package: Package{
139135
Name: importPath,
140136
Ecosystem: GoEcosystem,
141137
},
142-
Summary: "", // TODO: think if we want to populate this in reports
143-
Details: r.Description,
144-
Affects: generateAffects(r.Versions),
145-
LastModified: time.Now(),
146-
EcosystemSpecific: GoSpecific{
147-
Symbols: r.Symbols,
148-
GOOS: r.OS,
149-
GOARCH: r.Arch,
150-
URL: url,
138+
Details: r.Description,
139+
Affects: generateAffects(r.Versions),
140+
Extra: struct{ Go GoSpecific }{
141+
Go: GoSpecific{
142+
Symbols: r.Symbols,
143+
GOOS: r.OS,
144+
GOARCH: r.Arch,
145+
URL: url,
146+
},
151147
},
152148
}
153149

154-
if r.Severity != "" {
155-
entry.Severity = strToSev[r.Severity]
156-
} else {
157-
// Default to medium or none?
158-
entry.Severity = SevMedium
159-
}
160-
161150
if r.Links.PR != "" {
162-
entry.ReferenceURLs = append(entry.ReferenceURLs, r.Links.PR)
151+
entry.References = append(entry.References, Reference{Type: "code review", URL: r.Links.PR})
163152
}
164153
if r.Links.Commit != "" {
165-
entry.ReferenceURLs = append(entry.ReferenceURLs, r.Links.Commit)
154+
entry.References = append(entry.References, Reference{Type: "fix", URL: r.Links.Commit})
166155
}
167-
if r.Links.Context != nil {
168-
entry.ReferenceURLs = append(entry.ReferenceURLs, r.Links.Context...)
156+
for _, link := range r.Links.Context {
157+
entry.References = append(entry.References, Reference{Type: "misc", URL: link})
169158
}
170159

171160
if r.CVE != "" {
@@ -174,15 +163,15 @@ func Generate(id string, url string, r report.Report) []Entry {
174163

175164
entries := []Entry{entry}
176165

177-
// It would be better if this was just a recursive thing probably
166+
// It would be better if this was just a recursive thing maybe?
178167
for _, additional := range r.AdditionalPackages {
179168
entryCopy := entry
180169
additionalImportPath := additional.Module
181170
if additional.Package != "" {
182171
additionalImportPath = additional.Package
183172
}
184173
entryCopy.Package.Name = additionalImportPath
185-
entryCopy.EcosystemSpecific.Symbols = additional.Symbols
174+
entryCopy.Extra.Go.Symbols = additional.Symbols
186175
entryCopy.Affects = generateAffects(additional.Versions)
187176

188177
entries = append(entries, entryCopy)

osv/json_test.go

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ func TestGenerate(t *testing.T) {
3838
{Introduced: "v2.5.0"},
3939
},
4040
Description: "It's a real bad one, I'll tell you that",
41-
Severity: "medium",
4241
CVE: "CVE-0000-0000",
4342
Credit: "ignored",
4443
Symbols: []string{"A", "B.b"},
@@ -62,8 +61,7 @@ func TestGenerate(t *testing.T) {
6261
Name: "example.com/vulnerable/v2",
6362
Ecosystem: "go",
6463
},
65-
Details: "It's a real bad one, I'll tell you that",
66-
Severity: 2,
64+
Details: "It's a real bad one, I'll tell you that",
6765
Affects: Affects{
6866
Ranges: []AffectsRange{
6967
{
@@ -81,18 +79,20 @@ func TestGenerate(t *testing.T) {
8179
},
8280
},
8381
},
84-
ReferenceURLs: []string{
85-
"pr",
86-
"commit",
87-
"issue-a",
88-
"issue-b",
82+
References: []Reference{
83+
Reference{Type: "code review", URL: "pr"},
84+
Reference{Type: "fix", URL: "commit"},
85+
Reference{Type: "misc", URL: "issue-a"},
86+
Reference{Type: "misc", URL: "issue-b"},
8987
},
9088
Aliases: []string{"CVE-0000-0000"},
91-
EcosystemSpecific: GoSpecific{
92-
Symbols: []string{"A", "B.b"},
93-
GOOS: []string{"windows"},
94-
GOARCH: []string{"arm64"},
95-
URL: "https://vulns.golang.org/GO-1991-0001.html",
89+
Extra: struct{ Go GoSpecific }{
90+
Go: GoSpecific{
91+
Symbols: []string{"A", "B.b"},
92+
GOOS: []string{"windows"},
93+
GOARCH: []string{"arm64"},
94+
URL: "https://vulns.golang.org/GO-1991-0001.html",
95+
},
9696
},
9797
},
9898
{
@@ -102,8 +102,7 @@ func TestGenerate(t *testing.T) {
102102
Name: "vanity.host/vulnerable/package",
103103
Ecosystem: "go",
104104
},
105-
Details: "It's a real bad one, I'll tell you that",
106-
Severity: 2,
105+
Details: "It's a real bad one, I'll tell you that",
107106
Affects: Affects{
108107
Ranges: []AffectsRange{
109108
{
@@ -121,18 +120,20 @@ func TestGenerate(t *testing.T) {
121120
},
122121
},
123122
},
124-
ReferenceURLs: []string{
125-
"pr",
126-
"commit",
127-
"issue-a",
128-
"issue-b",
123+
References: []Reference{
124+
Reference{Type: "code review", URL: "pr"},
125+
Reference{Type: "fix", URL: "commit"},
126+
Reference{Type: "misc", URL: "issue-a"},
127+
Reference{Type: "misc", URL: "issue-b"},
129128
},
130129
Aliases: []string{"CVE-0000-0000"},
131-
EcosystemSpecific: GoSpecific{
132-
Symbols: []string{"b", "A.b"},
133-
GOOS: []string{"windows"},
134-
GOARCH: []string{"arm64"},
135-
URL: "https://vulns.golang.org/GO-1991-0001.html",
130+
Extra: struct{ Go GoSpecific }{
131+
Go: GoSpecific{
132+
Symbols: []string{"b", "A.b"},
133+
GOOS: []string{"windows"},
134+
GOARCH: []string{"arm64"},
135+
URL: "https://vulns.golang.org/GO-1991-0001.html",
136+
},
136137
},
137138
},
138139
}

report/lint.go

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,11 @@ func checkModVersions(path string, vr []VersionRange) error {
126126

127127
var cveRegex = regexp.MustCompile(`^CVE-\d{4}-\d{4,}$`)
128128

129+
// Lint checks the content of a Report.
130+
// TODO: instead of returning a single error we may want to return a slice, so that
131+
// we aren't fixing one thing at a time. Similarly it might make sense to include
132+
// warnings or informational things alongside errors, especially during for use
133+
// during the triage process.
129134
func (vuln *Report) Lint() error {
130135
var importPath string
131136
if !vuln.Stdlib {
@@ -184,17 +189,12 @@ func (vuln *Report) Lint() error {
184189
return errors.New("missing description")
185190
}
186191

187-
sevs := map[string]bool{
188-
"low": true,
189-
"medium": true,
190-
"high": true,
191-
"critical": true,
192+
if vuln.Published.IsZero() {
193+
return errors.New("missing published")
192194
}
193-
// Could also just default to medium if not provided?
194-
// Need to document what the default case is and what factors lower
195-
// or raise the sev
196-
if vuln.Severity != "" && !sevs[vuln.Severity] {
197-
return fmt.Errorf("unknown severity %q", vuln.Severity)
195+
196+
if vuln.LastModified != nil && vuln.LastModified.Before(vuln.Published) {
197+
return errors.New("last_modified is before published")
198198
}
199199

200200
if vuln.CVE != "" && vuln.CVEMetadata != nil && vuln.CVEMetadata.ID != "" {
@@ -203,7 +203,16 @@ func (vuln *Report) Lint() error {
203203
}
204204

205205
if vuln.CVE != "" && !cveRegex.MatchString(vuln.CVE) {
206-
return fmt.Errorf("malformed CVE number: %s", vuln.CVE)
206+
return fmt.Errorf("malformed cve: %s", vuln.CVE)
207+
}
208+
209+
if vuln.CVEMetadata != nil {
210+
if vuln.CVEMetadata.ID == "" {
211+
return errors.New("cve_metadata.id is required")
212+
}
213+
if !cveRegex.MatchString(vuln.CVEMetadata.ID) {
214+
return fmt.Errorf("malformed cve_metadata.id: %s", vuln.CVEMetadata.ID)
215+
}
207216
}
208217

209218
return nil

report/report.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ type Report struct {
3535
Versions []VersionRange
3636
Description string
3737
Published time.Time
38-
LastModified time.Time `toml:"last_modified"`
39-
Severity string
38+
LastModified *time.Time `toml:"last_modified"`
39+
Withdrawn *time.Time
4040
CVE string
4141
Credit string
4242
Symbols []string

reports/GO-2020-0001.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ credit = "@thinkerou <thinkerou@gmail.com>"
1212
# Test symbol inclusion by making a gin handler without Default or Logger.
1313
symbols = ["defaultLogFormatter"]
1414

15+
published = "2021-04-14T12:00:00Z"
16+
1517
[[versions]]
1618
# v1.5.1 doesn't exist? not sure how `go mod` is picking this pseudoversion
1719
fixed = "v1.6.0"
@@ -21,7 +23,7 @@ pr = "https://github.com/gin-gonic/gin/pull/2237"
2123
commit = "https://github.com/gin-gonic/gin/commit/a71af9c144f9579f6dbe945341c1df37aaf09c0d"
2224

2325
[cve_metadata]
24-
id = "CVE-XXXX-0001"
26+
id = "CVE-9999-0001"
2527
description = """
2628
Unsanitized input in the default logger in github.com/gin-gonic/gin before v1.6.0
2729
allows remote attackers to inject arbitary log lines.

reports/GO-2020-0002.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ leading to crashes and potentially code execution through a use-after-free.
1010

1111
credit = "Ulrich Obergfell <uobergfe@redhat.com>"
1212

13+
published = "2021-04-14T12:00:00Z"
14+
1315
[[versions]]
1416
fixed = "v0.1.1"
1517

reports/GO-2020-0003.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ crash by manipulating the request query.
99

1010
credit = "@SYM01"
1111

12+
published = "2021-04-14T12:00:00Z"
13+
1214
[[versions]]
1315
fixed = "v1.0.0"
1416

@@ -18,7 +20,7 @@ pr = "https://github.com/revel/revel/pull/1427"
1820
context = ["https://github.com/revel/revel/issues/1424"]
1921

2022
[cve_metadata]
21-
id = "CVE-XXXX-0002"
23+
id = "CVE-9999-0002"
2224
description = """
2325
Unsanitized input in the query parser in github.com/revel/revel before v1.0.0
2426
allows remote attackers to cause resource exhaustion via memory allocation.

0 commit comments

Comments
 (0)