all: update for OSV schema changes

The OSV affected.package.name field is now the module path, not the
package import path. The affected.package.ecosystem_speficic.imports
field now contains a list of Go packages and symbols within those
packages.

Restructure the report YAML to match the OSV structure:
A report contains a list of modules, a module contains a list of
packages, a package contains a list of symbols.

Move GOOS/GOARCH to the package, rather than being report-global.

This change updates the canonical YAML format and changes the
OSV generation to the new form, but does not reformat data/reports.
The report loader rewrites the old report YAML into the new
style. Followup CLs will convert the reports and remove the
rewriter.

Change-Id: I71af994846721fdd43a8ee5c41574387ff781332
Reviewed-on: https://go-review.googlesource.com/c/vulndb/+/424895
Reviewed-by: Julie Qiu <julieqiu@google.com>
Run-TryBot: Damien Neil <dneil@google.com>
This commit is contained in:
Damien Neil 2022-08-18 14:24:36 -07:00
Родитель 425ceb2f2b
Коммит 703236d8e9
20 изменённых файлов: 437 добавлений и 252 удалений

Просмотреть файл

@ -35,10 +35,12 @@ func TestExportedFunctions(t *testing.T) {
defer e.Cleanup() defer e.Cleanup()
rc := newReportClient(&report.Report{ rc := newReportClient(&report.Report{
Packages: []report.Package{{ Modules: []*report.Module{{
Module: "example.com/m", Module: "example.com/m",
Package: "example.com/m/p", Packages: []*report.Package{{
Symbols: []string{"vuln"}, Package: "example.com/m/p",
Symbols: []string{"vuln"},
}},
}}, }},
}) })
pkgs, err := loadPackage(e.Config, path.Join(e.Temp(), "m/p")) pkgs, err := loadPackage(e.Config, path.Join(e.Temp(), "m/p"))

Просмотреть файл

@ -239,28 +239,31 @@ func addTODOs(r *report.Report) {
if r.Excluded != "" { if r.Excluded != "" {
return return
} }
if len(r.Packages) == 0 { if len(r.Modules) == 0 {
r.Packages = append(r.Packages, report.Package{}) r.Modules = append(r.Modules, &report.Module{
Packages: []*report.Package{{}},
})
} }
for i := range r.Packages { for _, m := range r.Modules {
p := &r.Packages[i] if m.Module == "" {
if p.Module == "" && !stdlib.Contains(p.Module) { m.Module = todo
p.Module = todo
} }
if p.Package == "" { if len(m.Versions) == 0 {
p.Package = todo m.Versions = []report.VersionRange{{
}
if len(p.Versions) == 0 {
p.Versions = []report.VersionRange{{
Introduced: todo, Introduced: todo,
Fixed: todo, Fixed: todo,
}} }}
} }
if p.VulnerableAt == "" { if m.VulnerableAt == "" {
p.VulnerableAt = todo m.VulnerableAt = todo
} }
if len(p.Symbols) == 0 { for _, p := range m.Packages {
p.Symbols = []string{todo} if p.Package == "" {
p.Package = todo
}
if len(p.Symbols) == 0 {
p.Symbols = []string{todo}
}
} }
} }
if r.Description == "" { if r.Description == "" {
@ -319,41 +322,37 @@ func fix(ctx context.Context, filename string, accessToken string) (err error) {
} }
func checkReportSymbols(r *report.Report) (bool, error) { func checkReportSymbols(r *report.Report) (bool, error) {
if len(r.OS) > 0 || len(r.Arch) > 0 {
return false, errors.New("specific GOOS/GOARCH not yet implemented")
}
rc := newReportClient(r) rc := newReportClient(r)
added := false added := false
for i, p := range r.Packages { for _, m := range r.Modules {
if len(p.Symbols) == 0 { for _, p := range m.Packages {
continue if len(p.Symbols) == 0 {
} continue
syms, err := findExportedSymbols(p, rc) }
if err != nil { if len(p.GOOS) > 0 || len(p.GOARCH) > 0 {
return false, err return false, errors.New("specific GOOS/GOARCH not yet implemented")
} }
if !slices.Equal(syms, r.Packages[i].DerivedSymbols) { syms, err := findExportedSymbols(m, p, rc)
added = true if err != nil {
r.Packages[i].DerivedSymbols = syms return false, err
}
if !slices.Equal(syms, p.DerivedSymbols) {
added = true
p.DerivedSymbols = syms
}
} }
} }
return added, nil return added, nil
} }
func findExportedSymbols(p report.Package, c *reportClient) (_ []string, err error) { func findExportedSymbols(m *report.Module, p *report.Package, c *reportClient) (_ []string, err error) {
defer derrors.Wrap(&err, "addExportedSymbols(%q, %q)", p.Module, p.Package) defer derrors.Wrap(&err, "addExportedSymbols(%q, %q)", m.Module, p.Package)
if p.VulnerableAt == "" { if m.VulnerableAt == "" {
fmt.Fprintf(os.Stderr, "%v: no vulnerable_at version, skipping symbol checks.\n", p.Package) fmt.Fprintf(os.Stderr, "%v: no vulnerable_at version, skipping symbol checks.\n", p.Package)
return nil, nil return nil, nil
} }
module := p.Module
pkgPath := p.Package
if pkgPath == "" {
pkgPath = module
}
cleanup, err := changeToTempDir() cleanup, err := changeToTempDir()
if err != nil { if err != nil {
return nil, err return nil, err
@ -363,8 +362,8 @@ func findExportedSymbols(p report.Package, c *reportClient) (_ []string, err err
return nil, err return nil, err
} }
std := false std := false
if !stdlib.Contains(p.Module) { if m.Module != stdlib.ModulePath {
pkgPathAndVersion := pkgPath + "@" + p.VulnerableAt.V() pkgPathAndVersion := p.Package + "@" + m.VulnerableAt.V()
if err := run("go", "get", pkgPathAndVersion); err != nil { if err := run("go", "get", pkgPathAndVersion); err != nil {
return nil, err return nil, err
} }
@ -373,15 +372,15 @@ func findExportedSymbols(p report.Package, c *reportClient) (_ []string, err err
gover := runtime.Version() gover := runtime.Version()
ver := semverForGoVersion(gover) ver := semverForGoVersion(gover)
if ver == "" || !affected(c.entry, ver.V()) { if ver == "" || !affected(c.entry, ver.V()) {
fmt.Fprintf(os.Stderr, "%v: Go version %q is not in a vulnerable range, skipping symbol checks.\n", pkgPath, gover) fmt.Fprintf(os.Stderr, "%v: Go version %q is not in a vulnerable range, skipping symbol checks.\n", p.Package, gover)
return nil, nil return nil, nil
} }
if ver != p.VulnerableAt { if ver != m.VulnerableAt {
fmt.Fprintf(os.Stderr, "%v: WARNING: Go version %q does not match vulnerable_at version %q.\n", pkgPath, ver, p.VulnerableAt) fmt.Fprintf(os.Stderr, "%v: WARNING: Go version %q does not match vulnerable_at version %q.\n", p.Package, ver, m.VulnerableAt)
} }
} }
pkgs, err := loadPackage(&packages.Config{}, pkgPath) pkgs, err := loadPackage(&packages.Config{}, p.Package)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -389,16 +388,16 @@ func findExportedSymbols(p report.Package, c *reportClient) (_ []string, err err
return nil, errors.New("no packages found") return nil, errors.New("no packages found")
} }
// First package should match package path and module. // First package should match package path and module.
if pkgs[0].PkgPath != pkgPath { if pkgs[0].PkgPath != p.Package {
return nil, fmt.Errorf("first package had import path %s, wanted %s", pkgs[0].PkgPath, pkgPath) return nil, fmt.Errorf("first package had import path %s, wanted %s", pkgs[0].PkgPath, p.Package)
} }
if std { if std {
if pm := pkgs[0].Module; std && pm != nil { if pm := pkgs[0].Module; std && pm != nil {
return nil, fmt.Errorf("got module %v, expected nil", pm) return nil, fmt.Errorf("got module %v, expected nil", pm)
} }
} else { } else {
if pm := pkgs[0].Module; pm == nil || pm.Path != module { if pm := pkgs[0].Module; pm == nil || pm.Path != m.Module {
return nil, fmt.Errorf("got module %v, expected %s", pm, module) return nil, fmt.Errorf("got module %v, expected %s", pm, m.Module)
} }
} }

Просмотреть файл

@ -6,6 +6,8 @@ packages:
versions: versions:
- fixed: 0.0.0-20160903044734-789a4c4bd4c1 - fixed: 0.0.0-20160903044734-789a4c4bd4c1
- module: github.com/square/go-jose - module: github.com/square/go-jose
versions:
- fixed: 0.0.0-20160903044734-789a4c4bd4c1
symbols: symbols:
- JsonWebEncryption.Decrypt - JsonWebEncryption.Decrypt
- JsonWebEncryption.DecryptMulti - JsonWebEncryption.DecryptMulti

Просмотреть файл

@ -8,6 +8,8 @@ packages:
versions: versions:
- fixed: 0.0.0-20160831185616-c7581939a365 - fixed: 0.0.0-20160831185616-c7581939a365
- module: github.com/square/go-jose - module: github.com/square/go-jose
versions:
- fixed: 0.0.0-20160831185616-c7581939a365
symbols: symbols:
- JsonWebEncryption.Decrypt - JsonWebEncryption.Decrypt
description: | description: |

Просмотреть файл

@ -11,6 +11,8 @@ packages:
package: github.com/google/fscrypt/security package: github.com/google/fscrypt/security
symbols: symbols:
- UserKeyringID - UserKeyringID
versions:
- fixed: 0.2.4
description: | description: |
After dropping and then elevating process privileges euid, guid, and groups After dropping and then elevating process privileges euid, guid, and groups
are not properly restored to their original values, allowing an unprivileged are not properly restored to their original values, allowing an unprivileged

12
go.mod
Просмотреть файл

@ -3,7 +3,7 @@ module golang.org/x/vulndb
go 1.18 go 1.18
require ( require (
golang.org/x/vuln v0.0.0-20220504230052-b2400d8d07c8 golang.org/x/vuln v0.0.0-20220819162940-6faf8534b80b
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
) )
@ -25,14 +25,14 @@ require (
go.opentelemetry.io/otel v1.4.0 go.opentelemetry.io/otel v1.4.0
go.opentelemetry.io/otel/metric v0.27.0 go.opentelemetry.io/otel/metric v0.27.0
go.opentelemetry.io/otel/sdk v1.4.0 go.opentelemetry.io/otel/sdk v1.4.0
golang.org/x/exp v0.0.0-20220613132600-b0d781184e0d golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e
golang.org/x/exp/event v0.0.0-20220218215828-6cf2b201936e golang.org/x/exp/event v0.0.0-20220218215828-6cf2b201936e
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd golang.org/x/net v0.0.0-20220722155237-a158d28d115b
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 golang.org/x/time v0.0.0-20191024005414-555d28b269f0
golang.org/x/tools v0.1.11-0.20220504204054-4911e4af7dc7 golang.org/x/tools v0.1.13-0.20220803210227-8b9a1fbdf5c3
google.golang.org/api v0.70.0 google.golang.org/api v0.70.0
google.golang.org/grpc v1.44.0 google.golang.org/grpc v1.44.0
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
@ -71,7 +71,7 @@ require (
go.opentelemetry.io/otel/sdk/metric v0.26.0 // indirect go.opentelemetry.io/otel/sdk/metric v0.26.0 // indirect
go.opentelemetry.io/otel/trace v1.4.0 // indirect go.opentelemetry.io/otel/trace v1.4.0 // indirect
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
golang.org/x/sys v0.0.0-20220209214540-3681064d5158 // indirect golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
golang.org/x/text v0.3.7 // indirect golang.org/x/text v0.3.7 // indirect
google.golang.org/appengine v1.6.7 // indirect google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf // indirect google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf // indirect

21
go.sum
Просмотреть файл

@ -356,8 +356,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20220613132600-b0d781184e0d h1:vtUKgx8dahOomfFzLREU8nSv25YHnTgLBn4rDnWZdU0= golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA=
golang.org/x/exp v0.0.0-20220613132600-b0d781184e0d/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA=
golang.org/x/exp/event v0.0.0-20220218215828-6cf2b201936e h1:K2AuHMC+jaRTzAcivRwKOzjTZ1925Yx4xHMg07YoBQc= golang.org/x/exp/event v0.0.0-20220218215828-6cf2b201936e h1:K2AuHMC+jaRTzAcivRwKOzjTZ1925Yx4xHMg07YoBQc=
golang.org/x/exp/event v0.0.0-20220218215828-6cf2b201936e/go.mod h1:AVlZHjhWbW/3yOcmKMtJiObwBPJajBlUpQXRijFNrNc= golang.org/x/exp/event v0.0.0-20220218215828-6cf2b201936e/go.mod h1:AVlZHjhWbW/3yOcmKMtJiObwBPJajBlUpQXRijFNrNc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
@ -427,8 +427,9 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210716203947-853a461950ff/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210716203947-853a461950ff/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -457,8 +458,9 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -520,8 +522,9 @@ golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220207234003-57398862261d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220207234003-57398862261d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c=
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@ -592,10 +595,10 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/tools v0.1.11-0.20220504204054-4911e4af7dc7 h1:QA4ZyquqBP74mma6x4nQD4mSgYyTlie6xsnHTNOrOTI= golang.org/x/tools v0.1.13-0.20220803210227-8b9a1fbdf5c3 h1:aE4T3aJwdCNz+s35ScSQYUzeGu7BOLDHZ1bBHVurqqY=
golang.org/x/tools v0.1.11-0.20220504204054-4911e4af7dc7/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= golang.org/x/tools v0.1.13-0.20220803210227-8b9a1fbdf5c3/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/vuln v0.0.0-20220504230052-b2400d8d07c8 h1:ktGzfLSmromqTs5OnNke8ZkhPYxp+FBZl1OwYHAI0Ks= golang.org/x/vuln v0.0.0-20220819162940-6faf8534b80b h1:ik7eOhUcX1tUkjk2QMWi2uLpqwTzkH9aamJc3GbrSk8=
golang.org/x/vuln v0.0.0-20220504230052-b2400d8d07c8/go.mod h1:d4bTbXdZXwwxS/kocyDYvMPrnheQY7jl7nGUkXyWsH8= golang.org/x/vuln v0.0.0-20220819162940-6faf8534b80b/go.mod h1:7tDfEDtOLlzHQRi4Yzfg5seVBSvouUIjyPzBx4q5CxQ=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

Просмотреть файл

@ -12,6 +12,7 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"sort"
"strings" "strings"
"golang.org/x/vuln/client" "golang.org/x/vuln/client"
@ -184,17 +185,13 @@ func GenerateOSVEntry(id, url string, r report.Report) (osv.Entry, []string) {
} }
moduleMap := make(map[string]bool) moduleMap := make(map[string]bool)
for _, p := range r.Packages { for _, m := range r.Modules {
importPath := p.Module if m.Module == stdlib.ModulePath {
if p.Package != "" {
importPath = p.Package
}
if stdlib.Contains(p.Module) {
moduleMap[stdFileName] = true moduleMap[stdFileName] = true
} else { } else {
moduleMap[p.Module] = true moduleMap[m.Module] = true
} }
entry.Affected = append(entry.Affected, generateAffected(importPath, p.Versions, r.OS, r.Arch, p.AllSymbols(), url)) entry.Affected = append(entry.Affected, generateAffected(m, url))
} }
if r.Links.Advisory != "" { if r.Links.Advisory != "" {
@ -237,18 +234,35 @@ func generateAffectedRanges(versions []report.VersionRange) osv.Affects {
return osv.Affects{a} return osv.Affects{a}
} }
func generateAffected(importPath string, versions []report.VersionRange, goos, goarch, symbols []string, url string) osv.Affected { func generateImports(m *report.Module) (imps []osv.EcosystemSpecificImport) {
for _, p := range m.Packages {
syms := append([]string{}, p.Symbols...)
syms = append(syms, p.DerivedSymbols...)
sort.Strings(syms)
imps = append(imps, osv.EcosystemSpecificImport{
Path: p.Package,
GOOS: p.GOOS,
GOARCH: p.GOARCH,
Symbols: syms,
})
}
return imps
}
func generateAffected(m *report.Module, url string) osv.Affected {
name := m.Module
if name == stdlib.ModulePath {
name = "stdlib"
}
return osv.Affected{ return osv.Affected{
Package: osv.Package{ Package: osv.Package{
Name: importPath, Name: name,
Ecosystem: osv.GoEcosystem, Ecosystem: osv.GoEcosystem,
}, },
Ranges: generateAffectedRanges(versions), Ranges: generateAffectedRanges(m.Versions),
DatabaseSpecific: osv.DatabaseSpecific{URL: url}, DatabaseSpecific: osv.DatabaseSpecific{URL: url},
EcosystemSpecific: osv.EcosystemSpecific{ EcosystemSpecific: osv.EcosystemSpecific{
GOOS: goos, Imports: generateImports(m),
GOARCH: goarch,
Symbols: symbols,
}, },
} }
} }

Просмотреть файл

@ -17,7 +17,7 @@ import (
func TestGenerate(t *testing.T) { func TestGenerate(t *testing.T) {
r := report.Report{ r := report.Report{
Packages: []report.Package{ Modules: []*report.Module{
{ {
Module: "example.com/vulnerable/v2", Module: "example.com/vulnerable/v2",
Versions: []report.VersionRange{ Versions: []report.VersionRange{
@ -25,34 +25,49 @@ func TestGenerate(t *testing.T) {
{Introduced: "2.3.4", Fixed: "2.3.5"}, {Introduced: "2.3.4", Fixed: "2.3.5"},
{Introduced: "2.5.0"}, {Introduced: "2.5.0"},
}, },
Symbols: []string{"A", "B.b"}, Packages: []*report.Package{
DerivedSymbols: []string{"D"}, {
}, Package: "example.com/vulnerable/v2",
{ GOOS: []string{"windows"},
Module: "vanity.host/vulnerable", GOARCH: []string{"arm64"},
Package: "vanity.host/vulnerable/package", Symbols: []string{"A", "B.b"},
Symbols: []string{"b", "A.b"}, DerivedSymbols: []string{"D"},
},
},
}, {
Module: "vanity.host/vulnerable",
Versions: []report.VersionRange{ Versions: []report.VersionRange{
{Fixed: "2.1.1"}, {Fixed: "2.1.1"},
{Introduced: "2.3.4", Fixed: "2.3.5"}, {Introduced: "2.3.4", Fixed: "2.3.5"},
{Introduced: "2.5.0"}, {Introduced: "2.5.0"},
}, },
}, Packages: []*report.Package{
{ {
Module: "example.com/also-vulnerable", Package: "vanity.host/vulnerable/package",
Package: "example.com/also-vulnerable/package", GOOS: []string{"windows"},
Symbols: []string{"z"}, GOARCH: []string{"arm64"},
Symbols: []string{"A.b", "b"},
},
},
}, {
Module: "example.com/also-vulnerable",
Versions: []report.VersionRange{ Versions: []report.VersionRange{
{Fixed: "2.1.1"}, {Fixed: "2.1.1"},
}, },
Packages: []*report.Package{
{
Package: "example.com/also-vulnerable/package",
GOOS: []string{"windows"},
GOARCH: []string{"arm64"},
Symbols: []string{"z"},
},
},
}, },
}, },
Description: "It's a real bad one, I'll tell you that", Description: "It's a real bad one, I'll tell you that",
CVEs: []string{"CVE-0000-0000"}, CVEs: []string{"CVE-0000-0000"},
GHSAs: []string{"GHSA-abcd-efgh"}, GHSAs: []string{"GHSA-abcd-efgh"},
Credit: "ignored", Credit: "ignored",
OS: []string{"windows"},
Arch: []string{"arm64"},
Links: report.Links{ Links: report.Links{
PR: "pr", PR: "pr",
Commit: "commit", Commit: "commit",
@ -105,14 +120,19 @@ func TestGenerate(t *testing.T) {
}, },
DatabaseSpecific: osv.DatabaseSpecific{URL: url}, DatabaseSpecific: osv.DatabaseSpecific{URL: url},
EcosystemSpecific: osv.EcosystemSpecific{ EcosystemSpecific: osv.EcosystemSpecific{
Symbols: []string{"A", "B.b", "D"}, Imports: []osv.EcosystemSpecificImport{
GOOS: []string{"windows"}, {
GOARCH: []string{"arm64"}, Path: "example.com/vulnerable/v2",
GOOS: []string{"windows"},
GOARCH: []string{"arm64"},
Symbols: []string{"A", "B.b", "D"},
},
},
}, },
}, },
{ {
Package: osv.Package{ Package: osv.Package{
Name: "vanity.host/vulnerable/package", Name: "vanity.host/vulnerable",
Ecosystem: "Go", Ecosystem: "Go",
}, },
Ranges: []osv.AffectsRange{ Ranges: []osv.AffectsRange{
@ -139,14 +159,19 @@ func TestGenerate(t *testing.T) {
}, },
DatabaseSpecific: osv.DatabaseSpecific{URL: url}, DatabaseSpecific: osv.DatabaseSpecific{URL: url},
EcosystemSpecific: osv.EcosystemSpecific{ EcosystemSpecific: osv.EcosystemSpecific{
Symbols: []string{"b", "A.b"}, Imports: []osv.EcosystemSpecificImport{
GOOS: []string{"windows"}, {
GOARCH: []string{"arm64"}, Path: "vanity.host/vulnerable/package",
GOOS: []string{"windows"},
GOARCH: []string{"arm64"},
Symbols: []string{"A.b", "b"},
},
},
}, },
}, },
{ {
Package: osv.Package{ Package: osv.Package{
Name: "example.com/also-vulnerable/package", Name: "example.com/also-vulnerable",
Ecosystem: "Go", Ecosystem: "Go",
}, },
Ranges: []osv.AffectsRange{ Ranges: []osv.AffectsRange{
@ -164,9 +189,14 @@ func TestGenerate(t *testing.T) {
}, },
DatabaseSpecific: osv.DatabaseSpecific{URL: url}, DatabaseSpecific: osv.DatabaseSpecific{URL: url},
EcosystemSpecific: osv.EcosystemSpecific{ EcosystemSpecific: osv.EcosystemSpecific{
Symbols: []string{"z"}, Imports: []osv.EcosystemSpecificImport{
GOOS: []string{"windows"}, {
GOARCH: []string{"arm64"}, Path: "example.com/also-vulnerable/package",
GOOS: []string{"windows"},
GOARCH: []string{"arm64"},
Symbols: []string{"z"},
},
},
}, },
}, },
}, },

Просмотреть файл

@ -65,14 +65,14 @@ func ToCVE(reportPath string) (_ *cveschema.CVE, err error) {
}, },
} }
for _, p := range r.Packages { for _, m := range r.Modules {
c.Affects.Vendor.Data = append(c.Affects.Vendor.Data, cveschema.VendorDataItem{ c.Affects.Vendor.Data = append(c.Affects.Vendor.Data, cveschema.VendorDataItem{
VendorName: "n/a", // ??? VendorName: "n/a", // ???
Product: cveschema.Product{ Product: cveschema.Product{
Data: []cveschema.ProductDataItem{ Data: []cveschema.ProductDataItem{
{ {
ProductName: p.Package, ProductName: m.Module,
Version: versionToVersion(p.Versions), Version: versionToVersion(m.Versions),
}, },
}, },
}, },
@ -145,10 +145,18 @@ func CVEToReport(c *cveschema.CVE, modulePath string) *Report {
pkgPath = data2[0].ProductName pkgPath = data2[0].ProductName
} }
} }
if modulePath == "" {
modulePath = "TODO"
}
if pkgPath == "" {
pkgPath = modulePath
}
r := &Report{ r := &Report{
Packages: []Package{{ Modules: []*Module{{
Module: modulePath, Module: modulePath,
Package: pkgPath, Packages: []*Package{{
Package: pkgPath,
}},
}}, }},
Description: description, Description: description,
CVEs: []string{c.Metadata.ID}, CVEs: []string{c.Metadata.ID},
@ -160,11 +168,11 @@ func CVEToReport(c *cveschema.CVE, modulePath string) *Report {
}, },
} }
if !strings.Contains(modulePath, ".") { if !strings.Contains(modulePath, ".") {
r.Packages[0].Module = stdlib.ModulePath r.Modules[0].Module = stdlib.ModulePath
r.Packages[0].Package = modulePath r.Modules[0].Packages[0].Package = modulePath
} }
if stdlib.Contains(r.Packages[0].Module) && r.Packages[0].Package == "" { if stdlib.Contains(r.Modules[0].Module) && r.Modules[0].Packages[0].Package == "" {
r.Packages[0].Package = modulePath r.Modules[0].Packages[0].Package = modulePath
} }
r.Fix() r.Fix()
return r return r

Просмотреть файл

@ -72,22 +72,20 @@ func ToCVE5(reportPath string) (_ *cveschema5.CVERecord, err error) {
}, },
} }
for _, p := range r.Packages { for _, m := range r.Modules {
pkg := p.Package for _, p := range m.Packages {
if pkg == "" { affected := cveschema5.Affected{
pkg = p.Module CollectionURL: "https://pkg.go.dev",
PackageName: p.Package,
Versions: versionRangeToVersionRange(m.Versions),
DefaultStatus: cveschema5.StatusUnaffected,
Platforms: p.GOOS,
}
for _, symbol := range p.AllSymbols() {
affected.ProgramRoutines = append(affected.ProgramRoutines, cveschema5.ProgramRoutine{Name: symbol})
}
c.Affected = append(c.Affected, affected)
} }
affected := cveschema5.Affected{
CollectionURL: "https://pkg.go.dev",
PackageName: pkg,
Versions: versionRangeToVersionRange(p.Versions),
DefaultStatus: cveschema5.StatusUnaffected,
Platforms: r.OS,
}
for _, symbol := range p.AllSymbols() {
affected.ProgramRoutines = append(affected.ProgramRoutines, cveschema5.ProgramRoutine{Name: symbol})
}
c.Affected = append(c.Affected, affected)
} }
for _, link := range r.AllLinks() { for _, link := range r.AllLinks() {

Просмотреть файл

@ -5,9 +5,9 @@
package report package report
import ( import (
"reflect"
"testing" "testing"
"github.com/google/go-cmp/cmp"
"golang.org/x/vulndb/internal/cveschema5" "golang.org/x/vulndb/internal/cveschema5"
) )
@ -180,8 +180,8 @@ func TestToCVE5(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("ToCVE5(%s) failed unexpectedly; err=%v", test.filename, err) t.Fatalf("ToCVE5(%s) failed unexpectedly; err=%v", test.filename, err)
} }
if want := test.want; !reflect.DeepEqual(got, want) { if diff := cmp.Diff(test.want, got); diff != "" {
t.Fatalf("ToCVE5(%s)=\n%v\nwant=\n%v", test.filename, got, want) t.Fatalf("ToCVE5(%s): unexpected diffs (-want,+got):\n%v", test.filename, diff)
} }
}) })
} }

Просмотреть файл

@ -31,15 +31,18 @@ func GHSAToReport(sa *ghsa.SecurityAdvisory, modulePath string) *Report {
} }
r.CVEs = cves r.CVEs = cves
r.GHSAs = ghsas r.GHSAs = ghsas
for i, v := range sa.Vulns { if modulePath == "" {
p := Package{ modulePath = "TODO"
Package: v.Package, }
for _, v := range sa.Vulns {
m := &Module{
Module: modulePath,
Versions: versions(v.EarliestFixedVersion, v.VulnerableVersionRange), Versions: versions(v.EarliestFixedVersion, v.VulnerableVersionRange),
Packages: []*Package{{
Package: v.Package,
}},
} }
if i == 0 { r.Modules = append(r.Modules, m)
p.Module = modulePath
}
r.Packages = append(r.Packages, p)
} }
r.Fix() r.Fix()
return r return r

Просмотреть файл

@ -28,12 +28,14 @@ func TestGHSAToReport(t *testing.T) {
} }
got := GHSAToReport(sa, "aModule") got := GHSAToReport(sa, "aModule")
want := &Report{ want := &Report{
Packages: []Package{{ Modules: []*Module{{
Module: "aModule", Module: "aModule",
Package: "aPackage",
Versions: []VersionRange{ Versions: []VersionRange{
{Fixed: "1.2.3"}, {Fixed: "1.2.3"},
}, },
Packages: []*Package{{
Package: "aPackage",
}},
}}, }},
LastModified: &updatedTime, LastModified: &updatedTime,
Description: "a description", Description: "a description",

Просмотреть файл

@ -18,6 +18,7 @@ import (
"golang.org/x/mod/modfile" "golang.org/x/mod/modfile"
"golang.org/x/mod/module" "golang.org/x/mod/module"
"golang.org/x/mod/semver" "golang.org/x/mod/semver"
"golang.org/x/vulndb/internal/stdlib"
) )
// TODO: getting things from the proxy should all be cached so we // TODO: getting things from the proxy should all be cached so we
@ -147,41 +148,44 @@ func checkModVersions(modPath string, vrs []VersionRange) (err error) {
return nil return nil
} }
func (p *Package) lintStdLibPkg(addPkgIssue func(string)) { func (m *Module) lintStdLib(addPkgIssue func(string)) {
if p.Package == "" { if len(m.Packages) == 0 {
addPkgIssue("missing package") addPkgIssue("missing package")
} }
for _, p := range m.Packages {
if p.Package == "" {
addPkgIssue("missing package")
}
}
} }
func (p *Package) lintThirdPartyPkg(addPkgIssue func(string)) { func (m *Module) lintThirdParty(addPkgIssue func(string)) {
if p.Module == "" { if m.Module == "" {
addPkgIssue("missing module") addPkgIssue("missing module")
return return
} }
if p.Package == p.Module { if err := checkModVersions(m.Module, m.Versions); err != nil {
addPkgIssue("package is redundant and can be removed")
}
if p.Package != "" && !strings.HasPrefix(p.Package, p.Module) {
addPkgIssue("module must be a prefix of package")
}
if err := checkModVersions(p.Module, p.Versions); err != nil {
addPkgIssue(err.Error()) addPkgIssue(err.Error())
} }
for _, p := range m.Packages {
importPath := p.Package if p.Package == "" {
if p.Package == "" { addPkgIssue("missing package")
importPath = p.Module continue
} }
if err := module.CheckImportPath(importPath); err != nil { if !strings.HasPrefix(p.Package, m.Module) {
addPkgIssue(err.Error()) addPkgIssue("module must be a prefix of package")
}
if err := module.CheckImportPath(p.Package); err != nil {
addPkgIssue(err.Error())
}
} }
} }
func (p *Package) lintVersions(addPkgIssue func(string)) { func (m *Module) lintVersions(addPkgIssue func(string)) {
if p.VulnerableAt != "" && !p.VulnerableAt.IsValid() { if m.VulnerableAt != "" && !m.VulnerableAt.IsValid() {
addPkgIssue(fmt.Sprintf("invalid vulnerable_at semantic version: %q", p.VulnerableAt)) addPkgIssue(fmt.Sprintf("invalid vulnerable_at semantic version: %q", m.VulnerableAt))
} }
for i, vr := range p.Versions { for i, vr := range m.Versions {
for _, v := range []Version{vr.Introduced, vr.Fixed} { for _, v := range []Version{vr.Introduced, vr.Fixed} {
if v != "" && !v.IsValid() { if v != "" && !v.IsValid() {
addPkgIssue(fmt.Sprintf("invalid semantic version: %q", v)) addPkgIssue(fmt.Sprintf("invalid semantic version: %q", v))
@ -194,7 +198,7 @@ func (p *Package) lintVersions(addPkgIssue func(string)) {
} }
// Check all previous version ranges to ensure none overlap with // Check all previous version ranges to ensure none overlap with
// this one. // this one.
for _, vrPrev := range p.Versions[:i] { for _, vrPrev := range m.Versions[:i] {
if vrPrev.Introduced.Before(vr.Fixed) && vr.Introduced.Before(vrPrev.Fixed) { if vrPrev.Introduced.Before(vr.Fixed) && vr.Introduced.Before(vrPrev.Fixed) {
addPkgIssue(fmt.Sprintf("version ranges overlap: [%v,%v), [%v,%v)", vr.Introduced, vr.Fixed, vr.Introduced, vrPrev.Fixed)) addPkgIssue(fmt.Sprintf("version ranges overlap: [%v,%v), [%v,%v)", vr.Introduced, vr.Fixed, vr.Introduced, vrPrev.Fixed))
} }
@ -318,8 +322,8 @@ func (r *Report) Lint(filename string) []string {
if r.Excluded != "" { if r.Excluded != "" {
addIssue("report in reports/ must not have excluded set") addIssue("report in reports/ must not have excluded set")
} }
if len(r.Packages) == 0 { if len(r.Modules) == 0 {
addIssue("no packages") addIssue("no modules")
} }
if r.Description == "" { if r.Description == "" {
addIssue("missing description") addIssue("missing description")
@ -330,8 +334,8 @@ func (r *Report) Lint(filename string) []string {
} else if !slices.Contains(ExcludedReasons, r.Excluded) { } else if !slices.Contains(ExcludedReasons, r.Excluded) {
addIssue(fmt.Sprintf("excluded (%q) is not in set %v", r.Excluded, ExcludedReasons)) addIssue(fmt.Sprintf("excluded (%q) is not in set %v", r.Excluded, ExcludedReasons))
} }
if len(r.Packages) != 0 { if len(r.Modules) != 0 {
addIssue("excluded report should not have packages") addIssue("excluded report should not have modules")
} }
if len(r.CVEs) == 0 && len(r.GHSAs) == 0 { if len(r.CVEs) == 0 && len(r.GHSAs) == 0 {
addIssue("excluded report must have at least one associated CVE or GHSA") addIssue("excluded report must have at least one associated CVE or GHSA")
@ -339,19 +343,19 @@ func (r *Report) Lint(filename string) []string {
} }
isStdLibReport := false isStdLibReport := false
for i, p := range r.Packages { for i, m := range r.Modules {
addPkgIssue := func(iss string) { addPkgIssue := func(iss string) {
addIssue(fmt.Sprintf("packages[%v]: %v", i, iss)) addIssue(fmt.Sprintf("modules[%v]: %v", i, iss))
} }
if p.Module == "std" { if m.Module == stdlib.ModulePath {
isStdLibReport = true isStdLibReport = true
p.lintStdLibPkg(addPkgIssue) m.lintStdLib(addPkgIssue)
} else { } else {
p.lintThirdPartyPkg(addPkgIssue) m.lintThirdParty(addPkgIssue)
} }
p.lintVersions(addPkgIssue) m.lintVersions(addPkgIssue)
} }
if r.LastModified != nil && r.LastModified.Before(r.Published) { if r.LastModified != nil && r.LastModified.Before(r.Published) {
@ -396,15 +400,12 @@ func (r *Report) Fix() {
} }
*vp = v *vp = v
} }
for i, p := range r.Packages { for _, m := range r.Modules {
if p.Package == p.Module { for i := range m.Versions {
p.Package = "" fixVersion(&m.Versions[i].Introduced)
fixVersion(&m.Versions[i].Fixed)
} }
for j := range p.Versions { fixVersion(&m.VulnerableAt)
fixVersion(&r.Packages[i].Versions[j].Introduced)
fixVersion(&r.Packages[i].Versions[j].Fixed)
}
fixVersion(&r.Packages[i].VulnerableAt)
} }
r.Links.Context = fixed r.Links.Context = fixed
} }

Просмотреть файл

@ -34,18 +34,20 @@ func TestLint(t *testing.T) {
want []string want []string
}{ }{
{ {
desc: "no packages", desc: "no modules",
report: Report{ report: Report{
Description: "description", Description: "description",
}, },
want: []string{"no packages"}, want: []string{"no modules"},
}, },
{ {
desc: "missing module", desc: "missing module",
report: Report{ report: Report{
Packages: []Package{{ Modules: []*Module{{
// no module // mo module
Package: "golang.org/x/vulndb", Packages: []*Package{{
Package: "golang.org/x/vulndb",
}},
}}, }},
Description: "description", Description: "description",
}, },
@ -54,9 +56,11 @@ func TestLint(t *testing.T) {
{ {
desc: "missing description", desc: "missing description",
report: Report{ report: Report{
Packages: []Package{{ Modules: []*Module{{
Module: "std", Module: "std",
Package: "time", Packages: []*Package{{
Package: "time",
}},
}}, }},
// no description // no description
Links: validStdLibLinks, Links: validStdLibLinks,
@ -64,22 +68,26 @@ func TestLint(t *testing.T) {
want: []string{"missing description"}, want: []string{"missing description"},
}, },
{ {
desc: "third party: redundant module and package", desc: "missing package path",
report: Report{ report: Report{
Packages: []Package{{ Modules: []*Module{{
Module: "golang.org/x/vulndb", Module: "golang.org/x/vulndb",
Package: "golang.org/x/vulndb", Packages: []*Package{{
Symbols: []string{"Foo"},
}},
}}, }},
Description: "description", Description: "description",
}, },
want: []string{"package is redundant and can be removed"}, want: []string{"missing package"},
}, },
{ {
desc: "third party: module is not a prefix of package", desc: "third party: module is not a prefix of package",
report: Report{ report: Report{
Packages: []Package{{ Modules: []*Module{{
Module: "golang.org/x/vulndb", Module: "golang.org/x/vulndb",
Package: "golang.org/x/crypto", Packages: []*Package{{
Package: "golang.org/x/crypto",
}},
}}, }},
Description: "description", Description: "description",
}, },
@ -88,8 +96,11 @@ func TestLint(t *testing.T) {
{ {
desc: "third party: invalid import path", desc: "third party: invalid import path",
report: Report{ report: Report{
Packages: []Package{{ Modules: []*Module{{
Module: "invalid.", Module: "invalid.",
Packages: []*Package{{
Package: "invalid.",
}},
Versions: []VersionRange{{ Versions: []VersionRange{{
Fixed: "1.2.1", Fixed: "1.2.1",
}}, }},
@ -102,9 +113,12 @@ func TestLint(t *testing.T) {
{ {
desc: "standard library: missing package", desc: "standard library: missing package",
report: Report{ report: Report{
Packages: []Package{{ Modules: []*Module{{
Module: "std", Module: "std",
// no package Packages: []*Package{{
// no package
Symbols: []string{"Atoi"},
}},
}}, }},
Description: "description", Description: "description",
Links: validStdLibLinks, Links: validStdLibLinks,
@ -114,14 +128,16 @@ func TestLint(t *testing.T) {
{ {
desc: "overlapping version ranges", desc: "overlapping version ranges",
report: Report{ report: Report{
Packages: []Package{{ Modules: []*Module{{
Module: "std", Module: "std",
Package: "time",
Versions: []VersionRange{{ Versions: []VersionRange{{
Fixed: "1.2.1", Fixed: "1.2.1",
}, { }, {
Fixed: "1.3.2", Fixed: "1.3.2",
}}, }},
Packages: []*Package{{
Package: "time",
}},
}}, }},
Description: "description", Description: "description",
Links: validStdLibLinks, Links: validStdLibLinks,
@ -131,13 +147,15 @@ func TestLint(t *testing.T) {
{ {
desc: "fixed before introduced", desc: "fixed before introduced",
report: Report{ report: Report{
Packages: []Package{{ Modules: []*Module{{
Module: "std", Module: "std",
Package: "time",
Versions: []VersionRange{{ Versions: []VersionRange{{
Introduced: "1.3", Introduced: "1.3",
Fixed: "1.2.1", Fixed: "1.2.1",
}}, }},
Packages: []*Package{{
Package: "time",
}},
}}, }},
Description: "description", Description: "description",
Links: validStdLibLinks, Links: validStdLibLinks,
@ -147,12 +165,14 @@ func TestLint(t *testing.T) {
{ {
desc: "invalid semantic version", desc: "invalid semantic version",
report: Report{ report: Report{
Packages: []Package{{ Modules: []*Module{{
Module: "std", Module: "std",
Package: "time",
Versions: []VersionRange{{ Versions: []VersionRange{{
Introduced: "1.3.X", Introduced: "1.3.X",
}}, }},
Packages: []*Package{{
Package: "time",
}},
}}, }},
Description: "description", Description: "description",
Links: validStdLibLinks, Links: validStdLibLinks,
@ -162,9 +182,11 @@ func TestLint(t *testing.T) {
{ {
desc: "last modified before published", desc: "last modified before published",
report: Report{ report: Report{
Packages: []Package{{ Modules: []*Module{{
Module: "std", Module: "std",
Package: "time", Packages: []*Package{{
Package: "time",
}},
}}, }},
Description: "description", Description: "description",
LastModified: &jan2000, LastModified: &jan2000,
@ -176,9 +198,11 @@ func TestLint(t *testing.T) {
{ {
desc: "bad cve identifier", desc: "bad cve identifier",
report: Report{ report: Report{
Packages: []Package{{ Modules: []*Module{{
Module: "std", Module: "std",
Package: "time", Packages: []*Package{{
Package: "time",
}},
}}, }},
Description: "description", Description: "description",
CVEs: []string{"CVE.12345.456"}, CVEs: []string{"CVE.12345.456"},
@ -189,9 +213,11 @@ func TestLint(t *testing.T) {
{ {
desc: "cve and cve metadata both present", desc: "cve and cve metadata both present",
report: Report{ report: Report{
Packages: []Package{{ Modules: []*Module{{
Module: "std", Module: "std",
Package: "time", Packages: []*Package{{
Package: "time",
}},
}}, }},
Description: "description", Description: "description",
CVEs: []string{"CVE-2022-1234545"}, CVEs: []string{"CVE-2022-1234545"},
@ -205,9 +231,11 @@ func TestLint(t *testing.T) {
{ {
desc: "missing cve metadata id", desc: "missing cve metadata id",
report: Report{ report: Report{
Packages: []Package{{ Modules: []*Module{{
Module: "std", Module: "std",
Package: "time", Packages: []*Package{{
Package: "time",
}},
}}, }},
Description: "description", Description: "description",
CVEMetadata: &CVEMeta{ CVEMetadata: &CVEMeta{
@ -220,9 +248,11 @@ func TestLint(t *testing.T) {
{ {
desc: "bad cve metadata id", desc: "bad cve metadata id",
report: Report{ report: Report{
Packages: []Package{{ Modules: []*Module{{
Module: "std", Module: "std",
Package: "time", Packages: []*Package{{
Package: "time",
}},
}}, }},
Description: "description", Description: "description",
CVEMetadata: &CVEMeta{ CVEMetadata: &CVEMeta{
@ -235,8 +265,11 @@ func TestLint(t *testing.T) {
{ {
desc: "unfixed links", desc: "unfixed links",
report: Report{ report: Report{
Packages: []Package{{ Modules: []*Module{{
Module: "golang.org/x/vulndb", Module: "golang.org/x/vulndb",
Packages: []*Package{{
Package: "golang.org/x/vulndb",
}},
}}, }},
Description: "description", Description: "description",
Links: Links{ Links: Links{
@ -256,9 +289,11 @@ func TestLint(t *testing.T) {
{ {
desc: "standard library: unfixed/missing links", desc: "standard library: unfixed/missing links",
report: Report{ report: Report{
Packages: []Package{{ Modules: []*Module{{
Module: "std", Module: "std",
Package: "time", Packages: []*Package{{
Package: "time",
}},
}}, }},
Description: "description", Description: "description",
Links: Links{ Links: Links{
@ -285,8 +320,11 @@ func TestLint(t *testing.T) {
{ {
desc: "invalid URL", desc: "invalid URL",
report: Report{ report: Report{
Packages: []Package{{ Modules: []*Module{{
Module: "golang.org/x/vulndb", Module: "golang.org/x/vulndb",
Packages: []*Package{{
Package: "golang.org/x/vulndb",
}},
}}, }},
Description: "description", Description: "description",
Links: Links{ Links: Links{
@ -305,7 +343,7 @@ func TestLint(t *testing.T) {
}, },
want: []string{ want: []string{
`report in reports/ must not have excluded set`, `report in reports/ must not have excluded set`,
`no packages`, `no modules`,
`missing description`, `missing description`,
}, },
}, },

Просмотреть файл

@ -7,9 +7,11 @@
package report package report
import ( import (
"errors"
"fmt" "fmt"
"io" "io"
"os" "os"
"reflect"
"strings" "strings"
"time" "time"
@ -47,7 +49,31 @@ type VersionRange struct {
Fixed Version `yaml:"fixed,omitempty"` Fixed Version `yaml:"fixed,omitempty"`
} }
type Module struct {
Module string `yaml:",omitempty"`
Versions []VersionRange `yaml:",omitempty"`
// Known-vulnerable version, to use when performing static analysis or
// other techniques on a vulnerable version of the package.
//
// In general, we want to use the most recent vulnerable version of
// the package. Determining this programmatically is difficult, especially
// for packages without tagged versions, so we specify it manually here.
VulnerableAt Version `yaml:"vulnerable_at,omitempty"`
Packages []*Package `yaml:",omitempty"`
}
type Package struct { type Package struct {
Package string `yaml:",omitempty"`
GOOS []string `yaml:"goos,omitempty"`
GOARCH []string `yaml:"goarch,omitempty"`
// Symbols originally identified as vulnerable.
Symbols []string `yaml:",omitempty"`
// Additional vulnerable symbols, computed from Symbols via static analysis
// or other technique.
DerivedSymbols []string `yaml:"derived_symbols,omitempty"`
}
type LegacyPackage struct {
Module string `yaml:",omitempty"` Module string `yaml:",omitempty"`
Package string `yaml:",omitempty"` Package string `yaml:",omitempty"`
// Symbols originally identified as vulnerable. // Symbols originally identified as vulnerable.
@ -107,7 +133,7 @@ type Report struct {
// Excluded indicates an excluded report. // Excluded indicates an excluded report.
Excluded ExcludedReason `yaml:",omitempty"` Excluded ExcludedReason `yaml:",omitempty"`
Packages []Package `yaml:"packages,omitempty"` Modules []*Module `yaml:",omitempty"`
// Description is the CVE description from an existing CVE. If we are // Description is the CVE description from an existing CVE. If we are
// assigning a CVE ID ourselves, use CVEMetadata.Description instead. // assigning a CVE ID ourselves, use CVEMetadata.Description instead.
@ -123,15 +149,19 @@ type Report struct {
// the above CVEs. // the above CVEs.
GHSAs []string `yaml:",omitempty"` GHSAs []string `yaml:",omitempty"`
Credit string `yaml:",omitempty"` Credit string `yaml:",omitempty"`
OS []string `yaml:",omitempty"` Links Links `yaml:",omitempty"`
Arch []string `yaml:",omitempty"`
Links Links `yaml:",omitempty"`
// CVEMetdata is used to capture CVE information when we want to assign a // CVEMetdata is used to capture CVE information when we want to assign a
// CVE ourselves. If a CVE already exists for an issue, use the CVE field // CVE ourselves. If a CVE already exists for an issue, use the CVE field
// to fill in the ID string. // to fill in the ID string.
CVEMetadata *CVEMeta `yaml:"cve_metadata,omitempty"` CVEMetadata *CVEMeta `yaml:"cve_metadata,omitempty"`
// Pre-refactoring fields.
// TODO(dneil): Remove.
LegacyPackages []LegacyPackage `yaml:"packages,omitempty"`
LegacyOS []string `yaml:"os,omitempty"`
LegacyArch []string `yaml:"arch,omitempty"`
} }
// GetCVEs returns all CVE IDs for a report. // GetCVEs returns all CVE IDs for a report.
@ -208,9 +238,53 @@ func Read(filename string) (_ *Report, err error) {
if err := d.Decode(&r); err != nil { if err := d.Decode(&r); err != nil {
return nil, fmt.Errorf("yaml.Decode: %v", err) return nil, fmt.Errorf("yaml.Decode: %v", err)
} }
if err := r.upgrade(); err != nil {
return nil, err
}
return &r, nil return &r, nil
} }
// upgrade updates the format of a report from a prior syntax version
// to the current one.
//
// TODO(dneil): delete after all reports have been updated to the new syntax.
func (r *Report) upgrade() error {
if len(r.Modules) > 0 && len(r.LegacyPackages) > 0 {
return errors.New("modules and packages both set")
}
mods := make(map[string]*Module)
for _, p := range r.LegacyPackages {
mod := mods[p.Module]
if mod == nil {
mod = &Module{
Module: p.Module,
Versions: p.Versions,
VulnerableAt: p.VulnerableAt,
}
mods[p.Module] = mod
r.Modules = append(r.Modules, mod)
}
if !reflect.DeepEqual(mod.Versions, p.Versions) || mod.VulnerableAt != p.VulnerableAt {
return errors.New("inconsistent module versions")
}
name := p.Package
if name == "" {
name = p.Module
}
mod.Packages = append(mod.Packages, &Package{
Package: name,
GOOS: r.LegacyOS,
GOARCH: r.LegacyArch,
Symbols: p.Symbols,
DerivedSymbols: p.DerivedSymbols,
})
}
r.LegacyPackages = nil
return nil
}
// Write writes r to filename in YAML format. // Write writes r to filename in YAML format.
func (r *Report) Write(filename string) (err error) { func (r *Report) Write(filename string) (err error) {
f, err := os.Create(filename) f, err := os.Create(filename)

8
internal/report/testdata/report.yaml поставляемый
Просмотреть файл

@ -1,9 +1,11 @@
packages: modules:
- module: github.com/gin-gonic/gin - module: github.com/gin-gonic/gin
symbols:
- defaultLogFormatter
versions: versions:
- fixed: 1.6.0 - fixed: 1.6.0
packages:
- package: github.com/gin-gonic/gin
symbols:
- defaultLogFormatter
description: | description: |
The default Formatter for the Logger middleware (LoggerConfig.Formatter), The default Formatter for the Logger middleware (LoggerConfig.Formatter),
which is included in the Default engine, allows attackers to inject arbitrary which is included in the Default engine, allows attackers to inject arbitrary

13
internal/report/testdata/std-report.yaml поставляемый
Просмотреть файл

@ -2,15 +2,18 @@
# Use of this source code is governed by a BSD-style # Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file. # license that can be found in the LICENSE file.
packages: modules:
- module: std - module: std
package: crypto/rand
symbols:
- TestSymbol
versions: versions:
- fixed: 1.17.11 - fixed: 1.17.11
- introduced: 1.18.0 - introduced: 1.18.0
fixed: 1.18.3 fixed: 1.18.3
packages:
- package: crypto/rand
goos:
- windows
symbols:
- TestSymbol
description: | description: |
On Windows, TestSymbol will hang indefinitely if passed a large buffer. On Windows, TestSymbol will hang indefinitely if passed a large buffer.
cve_metadata: cve_metadata:
@ -19,8 +22,6 @@ cve_metadata:
description: | description: |
A description A description
credit: A Credit credit: A Credit
os:
- windows
links: links:
pr: https://go.dev/cl/12345 pr: https://go.dev/cl/12345
commit: https://go.googlesource.com/go/+/abcde commit: https://go.googlesource.com/go/+/abcde

Просмотреть файл

@ -232,8 +232,10 @@ Links:
See [doc/triage.md](https://github.com/golang/vulndb/blob/master/doc/triage.md) for instructions on how to triage this report. See [doc/triage.md](https://github.com/golang/vulndb/blob/master/doc/triage.md) for instructions on how to triage this report.
` + "```" + ` ` + "```" + `
packages: modules:
- module: a.Module - module: a.Module
packages:
- package: a.Module
description: | description: |
a description a description
cves: cves:
@ -272,10 +274,12 @@ func TestNewGHSABody(t *testing.T) {
See [doc/triage.md](https://github.com/golang/vulndb/blob/master/doc/triage.md) for instructions on how to triage this report. See [doc/triage.md](https://github.com/golang/vulndb/blob/master/doc/triage.md) for instructions on how to triage this report.
` + "```" + ` ` + "```" + `
packages: modules:
- package: aPackage - module: TODO
versions: versions:
- fixed: 1.2.3 - fixed: 1.2.3
packages:
- package: aPackage
description: a description description: a description
ghsas: ghsas:
- G1 - G1