зеркало из https://github.com/golang/vulndb.git
internal/database: add more tests for Load
Adds tests for Load failure cases, adds more context to error message, and adds an additional failure case. For golang/go#56417 Change-Id: If4927c11f433c931827b262ee65a04f3594a125a Reviewed-on: https://go-review.googlesource.com/c/vulndb/+/453175 Reviewed-by: Damien Neil <dneil@google.com> Reviewed-by: Jonathan Amsterdam <jba@google.com> Run-TryBot: Tatiana Bradley <tatiana@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
Родитель
5d80fbd803
Коммит
f983c1a9a8
|
@ -54,7 +54,7 @@ func rawLoad(dbPath string) (_ *Database, err error) {
|
|||
}
|
||||
|
||||
if err := report.UnmarshalFromFile(filepath.Join(dbPath, indexFile), &d.Index); err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("invalid or missing index.json: %v", err)
|
||||
}
|
||||
|
||||
d.EntriesByModule, err = loadEntriesByModule(dbPath, d.Index)
|
||||
|
@ -68,7 +68,7 @@ func rawLoad(dbPath string) (_ *Database, err error) {
|
|||
}
|
||||
|
||||
if err := report.UnmarshalFromFile(filepath.Join(dbPath, aliasesFile), &d.IDsByAlias); err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("invalid or missing aliases.json: %v", err)
|
||||
}
|
||||
|
||||
return d, nil
|
||||
|
@ -102,7 +102,7 @@ func (d *Database) checkNoUnexpectedFiles(dbPath string) error {
|
|||
}
|
||||
id := report.GetGoIDFromFilename(fname)
|
||||
if _, ok := d.EntriesByID[id]; !ok {
|
||||
return fmt.Errorf("found unexpected ID %q which is not present in %s", id, filepath.Join(idDirectory, indexFile))
|
||||
return fmt.Errorf("found unexpected file %q which is not present in %s", fname, filepath.Join(idDirectory, indexFile))
|
||||
}
|
||||
// All other files should have corresponding entries in
|
||||
// EntriesByModule.
|
||||
|
@ -153,6 +153,18 @@ func (d *Database) checkInternalConsistency() error {
|
|||
if !reflect.DeepEqual(entry, entryByID) {
|
||||
return fmt.Errorf("inconsistent OSV contents in module and ID advisory for %s", entry.ID)
|
||||
}
|
||||
|
||||
var found bool
|
||||
for _, affected := range entry.Affected {
|
||||
m := affected.Package.Name
|
||||
if m == module {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return fmt.Errorf("%s does not reference %s", entry.ID, module)
|
||||
}
|
||||
}
|
||||
if modified != wantModified {
|
||||
return fmt.Errorf("incorrect modified timestamp for module %s: want %s, got %s", module, wantModified, modified)
|
||||
|
@ -190,7 +202,7 @@ func (d *Database) checkInternalConsistency() error {
|
|||
}
|
||||
}
|
||||
if !found {
|
||||
return fmt.Errorf("%s is not listed as an alias of %s", entry.ID, alias)
|
||||
return fmt.Errorf("%s is not listed as an alias of %s in aliases.json", entry.ID, alias)
|
||||
}
|
||||
}
|
||||
if entry.Published.After(entry.Modified) {
|
||||
|
@ -202,7 +214,7 @@ func (d *Database) checkInternalConsistency() error {
|
|||
for _, goID := range goIDs {
|
||||
entry, ok := d.EntriesByID[goID]
|
||||
if !ok {
|
||||
return fmt.Errorf("no advisory found for ID %s listed under %s", goID, alias)
|
||||
return fmt.Errorf("no advisory found for %s listed under %s", goID, alias)
|
||||
}
|
||||
|
||||
if !slices.Contains(entry.Aliases, alias) {
|
||||
|
@ -217,7 +229,7 @@ func (d *Database) checkInternalConsistency() error {
|
|||
func loadEntriesByID(dbPath string) (EntriesByID, error) {
|
||||
var ids []string
|
||||
if err := report.UnmarshalFromFile(filepath.Join(dbPath, idDirectory, indexFile), &ids); err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("invalid or missing ID/index.json: %v", err)
|
||||
}
|
||||
|
||||
entriesByID := make(EntriesByID, len(ids))
|
||||
|
@ -225,7 +237,7 @@ func loadEntriesByID(dbPath string) (EntriesByID, error) {
|
|||
var entry osv.Entry
|
||||
err := report.UnmarshalFromFile(filepath.Join(dbPath, idDirectory, id+".json"), &entry)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("invalid or missing OSV file: %v", err)
|
||||
}
|
||||
entriesByID[id] = &entry
|
||||
}
|
||||
|
@ -243,7 +255,7 @@ func loadEntriesByModule(dbPath string, index client.DBIndex) (EntriesByModule,
|
|||
var entries []*osv.Entry
|
||||
err = report.UnmarshalFromFile(fpath, &entries)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("invalid or missing module directory: %v", err)
|
||||
}
|
||||
entriesByModule[module] = entries
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
package database
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -13,9 +14,6 @@ import (
|
|||
"golang.org/x/vuln/osv"
|
||||
)
|
||||
|
||||
// TODO(https://github.com/golang/go#56417): Write unit tests for various
|
||||
// invalid databases.
|
||||
|
||||
var (
|
||||
validDir = "testdata/db/valid"
|
||||
jan1999 = time.Date(1999, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||
|
@ -123,13 +121,217 @@ var valid = &Database{
|
|||
}
|
||||
|
||||
func TestLoad(t *testing.T) {
|
||||
path := validDir
|
||||
got, err := Load(path)
|
||||
if err != nil {
|
||||
t.Fatalf("Load(%s): want succeess, got %s", path, err)
|
||||
t.Run("ok", func(t *testing.T) {
|
||||
path := validDir
|
||||
got, err := Load(path)
|
||||
if err != nil {
|
||||
t.Fatalf("Load(%s): want succeess, got %s", path, err)
|
||||
}
|
||||
want := valid
|
||||
if diff := cmp.Diff(want, got); diff != "" {
|
||||
t.Errorf("Load(%s): unexpected diff (want- got+):\n %s", path, diff)
|
||||
}
|
||||
})
|
||||
|
||||
failTests := []struct {
|
||||
name string
|
||||
dbPath string
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "missing file",
|
||||
dbPath: "testdata/db/missing-file",
|
||||
wantErr: "invalid or missing",
|
||||
},
|
||||
{
|
||||
name: "unexpected file",
|
||||
dbPath: "testdata/db/unexpected-file",
|
||||
wantErr: "found unexpected file",
|
||||
},
|
||||
}
|
||||
want := valid
|
||||
if diff := cmp.Diff(want, got); diff != "" {
|
||||
t.Errorf("Load(%s): unexpected diff (want- got+):\n %s", path, diff)
|
||||
for _, test := range failTests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
_, err := Load(test.dbPath)
|
||||
if err == nil || !strings.Contains(err.Error(), test.wantErr) {
|
||||
t.Fatalf("Load(%s): want err containing %s, got %v", test.dbPath, test.wantErr, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckInternalConsistency(t *testing.T) {
|
||||
t.Run("ok", func(t *testing.T) {
|
||||
if err := valid.checkInternalConsistency(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
})
|
||||
|
||||
failTests := []struct {
|
||||
name string
|
||||
db *Database
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "too many modules",
|
||||
db: &Database{
|
||||
EntriesByModule: EntriesByModule{"module": []*osv.Entry{}},
|
||||
},
|
||||
wantErr: "length mismatch",
|
||||
},
|
||||
{
|
||||
name: "missing module from index",
|
||||
db: &Database{
|
||||
Index: client.DBIndex{"module": time.Time{}},
|
||||
EntriesByModule: EntriesByModule{"module2": []*osv.Entry{}},
|
||||
},
|
||||
wantErr: "no module directory found",
|
||||
},
|
||||
{
|
||||
name: "missing OSV from module reference",
|
||||
db: &Database{
|
||||
Index: client.DBIndex{"module": time.Time{}},
|
||||
EntriesByModule: EntriesByModule{"module": []*osv.Entry{
|
||||
{ID: "GO-1999-0001"},
|
||||
}},
|
||||
EntriesByID: EntriesByID{},
|
||||
},
|
||||
wantErr: "no advisory found for ID GO-1999-0001",
|
||||
},
|
||||
{
|
||||
name: "inconsistent OSV",
|
||||
db: &Database{
|
||||
Index: client.DBIndex{"module": time.Time{}},
|
||||
EntriesByModule: EntriesByModule{"module": []*osv.Entry{
|
||||
{ID: "GO-1999-0001"},
|
||||
}},
|
||||
EntriesByID: EntriesByID{"GO-1999-0001": {ID: "GO-1999-0001",
|
||||
Published: jan1999}},
|
||||
},
|
||||
wantErr: "inconsistent OSV contents",
|
||||
},
|
||||
{
|
||||
name: "incorrect modified timestamp in index",
|
||||
db: &Database{
|
||||
Index: client.DBIndex{"module": jan2000},
|
||||
EntriesByModule: EntriesByModule{"module": []*osv.Entry{
|
||||
{ID: "GO-1999-0001", Modified: jan1999,
|
||||
Affected: []osv.Affected{
|
||||
{
|
||||
Package: osv.Package{
|
||||
Name: "module",
|
||||
},
|
||||
},
|
||||
}},
|
||||
}},
|
||||
EntriesByID: EntriesByID{"GO-1999-0001": {ID: "GO-1999-0001",
|
||||
Modified: jan1999, Affected: []osv.Affected{
|
||||
{
|
||||
Package: osv.Package{
|
||||
Name: "module",
|
||||
},
|
||||
},
|
||||
}}},
|
||||
},
|
||||
wantErr: "incorrect modified timestamp",
|
||||
},
|
||||
{
|
||||
name: "missing module referenced by OSV",
|
||||
db: &Database{
|
||||
Index: client.DBIndex{},
|
||||
EntriesByModule: EntriesByModule{},
|
||||
EntriesByID: EntriesByID{"GO-1999-0001": {ID: "GO-1999-0001",
|
||||
Affected: []osv.Affected{
|
||||
{
|
||||
Package: osv.Package{
|
||||
Name: "a/module",
|
||||
},
|
||||
},
|
||||
},
|
||||
}}},
|
||||
wantErr: "module a/module not found",
|
||||
},
|
||||
{
|
||||
name: "OSV does not reference module",
|
||||
db: &Database{
|
||||
Index: client.DBIndex{"module": time.Time{}},
|
||||
EntriesByModule: EntriesByModule{"module": []*osv.Entry{
|
||||
{ID: "GO-1999-0001"},
|
||||
}},
|
||||
EntriesByID: EntriesByID{"GO-1999-0001": {ID: "GO-1999-0001"}},
|
||||
},
|
||||
wantErr: "GO-1999-0001 does not reference module",
|
||||
},
|
||||
{
|
||||
name: "missing OSV entry in module",
|
||||
db: &Database{
|
||||
Index: client.DBIndex{"module": time.Time{}},
|
||||
EntriesByModule: EntriesByModule{"module": []*osv.Entry{
|
||||
{ID: "GO-1999-0002",
|
||||
Affected: []osv.Affected{
|
||||
{
|
||||
Package: osv.Package{
|
||||
Name: "module",
|
||||
},
|
||||
},
|
||||
},
|
||||
}}},
|
||||
EntriesByID: EntriesByID{"GO-1999-0001": {ID: "GO-1999-0001",
|
||||
Affected: []osv.Affected{
|
||||
{
|
||||
Package: osv.Package{
|
||||
Name: "module",
|
||||
},
|
||||
},
|
||||
},
|
||||
}, "GO-1999-0002": {ID: "GO-1999-0002",
|
||||
Affected: []osv.Affected{
|
||||
{
|
||||
Package: osv.Package{
|
||||
Name: "module",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}},
|
||||
wantErr: "GO-1999-0001 does not have an entry in module",
|
||||
},
|
||||
{
|
||||
name: "missing alias in aliases.json",
|
||||
db: &Database{
|
||||
EntriesByID: EntriesByID{"GO-1999-0001": {ID: "GO-1999-0001", Aliases: []string{"CVE-1999-0001"}}},
|
||||
IDsByAlias: IDsByAlias{},
|
||||
},
|
||||
wantErr: "alias CVE-1999-0001 not found",
|
||||
},
|
||||
{
|
||||
name: "missing OSV reference in aliases.json",
|
||||
db: &Database{
|
||||
EntriesByID: EntriesByID{"GO-1999-0001": {ID: "GO-1999-0001", Aliases: []string{"CVE-1999-0001"}}},
|
||||
IDsByAlias: IDsByAlias{"CVE-1999-0001": []string{"GO-2000-2222"}},
|
||||
},
|
||||
wantErr: "GO-1999-0001 is not listed as an alias of CVE-1999-0001",
|
||||
},
|
||||
{
|
||||
name: "missing OSV referenced by aliases.json",
|
||||
db: &Database{
|
||||
IDsByAlias: IDsByAlias{"CVE-1999-0001": []string{"GO-1999-0001"}},
|
||||
},
|
||||
wantErr: "no advisory found for GO-1999-0001 listed under CVE-1999-0001",
|
||||
},
|
||||
{
|
||||
name: "missing alias in OSV",
|
||||
db: &Database{
|
||||
EntriesByID: EntriesByID{"GO-1999-0001": {ID: "GO-1999-0001"}},
|
||||
IDsByAlias: IDsByAlias{"CVE-1999-0001": []string{"GO-1999-0001"}},
|
||||
},
|
||||
wantErr: "advisory GO-1999-0001 does not reference alias CVE-1999-0001",
|
||||
},
|
||||
}
|
||||
for _, test := range failTests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
if err := test.db.checkInternalConsistency(); err == nil || !strings.Contains(err.Error(), test.wantErr) {
|
||||
t.Errorf("want error containing %q, got %v", test.wantErr, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
{
|
||||
"id": "GO-1999-0001",
|
||||
"published": "1999-01-01T00:00:00Z",
|
||||
"modified": "2001-01-01T00:00:00Z",
|
||||
"aliases": [
|
||||
"CVE-1999-1111"
|
||||
],
|
||||
"details": "Some details",
|
||||
"affected": [
|
||||
{
|
||||
"package": {
|
||||
"name": "example.com/module",
|
||||
"ecosystem": "Go"
|
||||
},
|
||||
"ranges": [
|
||||
{
|
||||
"type": "SEMVER",
|
||||
"events": [
|
||||
{
|
||||
"introduced": "0"
|
||||
},
|
||||
{
|
||||
"fixed": "1.1.0"
|
||||
},
|
||||
{
|
||||
"introduced": "1.2.0"
|
||||
},
|
||||
{
|
||||
"fixed": "1.2.2"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"database_specific": {
|
||||
"url": "https://pkg.go.dev/vuln/GO-1999-0001"
|
||||
},
|
||||
"ecosystem_specific": {
|
||||
"imports": [
|
||||
{
|
||||
"path": "package",
|
||||
"symbols": [
|
||||
"Symbol"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"type": "FIX",
|
||||
"url": "https://example.com/cl/123"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
"id": "GO-2000-0002",
|
||||
"published": "2000-01-01T00:00:00Z",
|
||||
"modified": "2001-01-01T00:00:00Z",
|
||||
"aliases": [
|
||||
"CVE-1999-2222"
|
||||
],
|
||||
"details": "Some details",
|
||||
"affected": [
|
||||
{
|
||||
"package": {
|
||||
"name": "example.com/module2",
|
||||
"ecosystem": "Go"
|
||||
},
|
||||
"ranges": [
|
||||
{
|
||||
"type": "SEMVER",
|
||||
"events": [
|
||||
{
|
||||
"introduced": "0"
|
||||
},
|
||||
{
|
||||
"fixed": "1.2.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"database_specific": {
|
||||
"url": "https://pkg.go.dev/vuln/GO-2000-0002"
|
||||
},
|
||||
"ecosystem_specific": {
|
||||
"imports": [
|
||||
{
|
||||
"path": "package",
|
||||
"symbols": [
|
||||
"Symbol"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"type": "FIX",
|
||||
"url": "https://example.com/cl/543"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
[
|
||||
"GO-1999-0001",
|
||||
"GO-2000-0002"
|
||||
]
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"CVE-1999-1111": [
|
||||
"GO-1999-0001"
|
||||
],
|
||||
"CVE-1999-2222": [
|
||||
"GO-2000-0002"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
[
|
||||
{
|
||||
"id": "GO-1999-0001",
|
||||
"published": "1999-01-01T00:00:00Z",
|
||||
"modified": "2001-01-01T00:00:00Z",
|
||||
"aliases": [
|
||||
"CVE-1999-1111"
|
||||
],
|
||||
"details": "Some details",
|
||||
"affected": [
|
||||
{
|
||||
"package": {
|
||||
"name": "example.com/module",
|
||||
"ecosystem": "Go"
|
||||
},
|
||||
"ranges": [
|
||||
{
|
||||
"type": "SEMVER",
|
||||
"events": [
|
||||
{
|
||||
"introduced": "0"
|
||||
},
|
||||
{
|
||||
"fixed": "1.1.0"
|
||||
},
|
||||
{
|
||||
"introduced": "1.2.0"
|
||||
},
|
||||
{
|
||||
"fixed": "1.2.2"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"database_specific": {
|
||||
"url": "https://pkg.go.dev/vuln/GO-1999-0001"
|
||||
},
|
||||
"ecosystem_specific": {
|
||||
"imports": [
|
||||
{
|
||||
"path": "package",
|
||||
"symbols": [
|
||||
"Symbol"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"type": "FIX",
|
||||
"url": "https://example.com/cl/123"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"example.com/module": "2001-01-01T00:00:00Z",
|
||||
"example.com/module2": "2001-01-01T00:00:00Z"
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
{
|
||||
"id": "GO-1999-0001",
|
||||
"published": "1999-01-01T00:00:00Z",
|
||||
"modified": "2002-01-01T00:00:00Z",
|
||||
"aliases": [
|
||||
"CVE-1999-1111"
|
||||
],
|
||||
"details": "Some details",
|
||||
"affected": [
|
||||
{
|
||||
"package": {
|
||||
"name": "example.com/module",
|
||||
"ecosystem": "Go"
|
||||
},
|
||||
"ranges": [
|
||||
{
|
||||
"type": "SEMVER",
|
||||
"events": [
|
||||
{
|
||||
"introduced": "0"
|
||||
},
|
||||
{
|
||||
"fixed": "1.1.0"
|
||||
},
|
||||
{
|
||||
"introduced": "1.2.0"
|
||||
},
|
||||
{
|
||||
"fixed": "1.2.2"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"database_specific": {
|
||||
"url": "https://pkg.go.dev/vuln/GO-1999-0001"
|
||||
},
|
||||
"ecosystem_specific": {
|
||||
"imports": [
|
||||
{
|
||||
"path": "package",
|
||||
"symbols": [
|
||||
"Symbol"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"type": "FIX",
|
||||
"url": "https://example.com/cl/123"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
"id": "GO-2000-0002",
|
||||
"published": "2000-01-01T00:00:00Z",
|
||||
"modified": "2002-01-01T00:00:00Z",
|
||||
"aliases": [
|
||||
"CVE-1999-2222"
|
||||
],
|
||||
"details": "Some details",
|
||||
"affected": [
|
||||
{
|
||||
"package": {
|
||||
"name": "example.com/module2",
|
||||
"ecosystem": "Go"
|
||||
},
|
||||
"ranges": [
|
||||
{
|
||||
"type": "SEMVER",
|
||||
"events": [
|
||||
{
|
||||
"introduced": "0"
|
||||
},
|
||||
{
|
||||
"fixed": "1.2.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"database_specific": {
|
||||
"url": "https://pkg.go.dev/vuln/GO-2000-0002"
|
||||
},
|
||||
"ecosystem_specific": {
|
||||
"imports": [
|
||||
{
|
||||
"path": "package",
|
||||
"symbols": [
|
||||
"Symbol"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"type": "FIX",
|
||||
"url": "https://example.com/cl/543"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
[
|
||||
"GO-1999-0001"
|
||||
]
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"CVE-1999-1111": [
|
||||
"GO-1999-0001"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
[
|
||||
{
|
||||
"id": "GO-1999-0001",
|
||||
"published": "1999-01-01T00:00:00Z",
|
||||
"modified": "2002-01-01T00:00:00Z",
|
||||
"aliases": [
|
||||
"CVE-1999-1111"
|
||||
],
|
||||
"details": "Some details",
|
||||
"affected": [
|
||||
{
|
||||
"package": {
|
||||
"name": "example.com/module",
|
||||
"ecosystem": "Go"
|
||||
},
|
||||
"ranges": [
|
||||
{
|
||||
"type": "SEMVER",
|
||||
"events": [
|
||||
{
|
||||
"introduced": "0"
|
||||
},
|
||||
{
|
||||
"fixed": "1.1.0"
|
||||
},
|
||||
{
|
||||
"introduced": "1.2.0"
|
||||
},
|
||||
{
|
||||
"fixed": "1.2.2"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"database_specific": {
|
||||
"url": "https://pkg.go.dev/vuln/GO-1999-0001"
|
||||
},
|
||||
"ecosystem_specific": {
|
||||
"imports": [
|
||||
{
|
||||
"path": "package",
|
||||
"symbols": [
|
||||
"Symbol"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"type": "FIX",
|
||||
"url": "https://example.com/cl/123"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"example.com/module": "2002-01-01T00:00:00Z"
|
||||
}
|
Загрузка…
Ссылка в новой задаче