78 lines
2.1 KiB
Go
78 lines
2.1 KiB
Go
// Copyright 2023 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package client
|
|
|
|
import (
|
|
"encoding/json"
|
|
"path"
|
|
"sort"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
idDir = "ID"
|
|
indexDir = "index"
|
|
)
|
|
|
|
var (
|
|
dbEndpoint = path.Join(indexDir, "db")
|
|
modulesEndpoint = path.Join(indexDir, "modules")
|
|
)
|
|
|
|
func entryEndpoint(id string) string {
|
|
return path.Join(idDir, id)
|
|
}
|
|
|
|
// dbMeta contains metadata about the database itself.
|
|
type dbMeta struct {
|
|
// Modified is the time the database was last modified, calculated
|
|
// as the most recent time any single OSV entry was modified.
|
|
Modified time.Time `json:"modified"`
|
|
}
|
|
|
|
// moduleMeta contains metadata about a Go module that has one
|
|
// or more vulnerabilities in the database.
|
|
//
|
|
// Found in the "index/modules" endpoint of the vulnerability database.
|
|
type moduleMeta struct {
|
|
// Path is the module path.
|
|
Path string `json:"path"`
|
|
// Vulns is a list of vulnerabilities that affect this module.
|
|
Vulns []moduleVuln `json:"vulns"`
|
|
}
|
|
|
|
// moduleVuln contains metadata about a vulnerability that affects
|
|
// a certain module.
|
|
type moduleVuln struct {
|
|
// ID is a unique identifier for the vulnerability.
|
|
// The Go vulnerability database issues IDs of the form
|
|
// GO-<YEAR>-<ENTRYID>.
|
|
ID string `json:"id"`
|
|
// Modified is the time the vuln was last modified.
|
|
Modified time.Time `json:"modified"`
|
|
// Fixed is the latest version that introduces a fix for the
|
|
// vulnerability, in SemVer 2.0.0 format, with no leading "v" prefix.
|
|
Fixed string `json:"fixed,omitempty"`
|
|
}
|
|
|
|
// modulesIndex represents an in-memory modules index.
|
|
type modulesIndex map[string]*moduleMeta
|
|
|
|
func (m modulesIndex) MarshalJSON() ([]byte, error) {
|
|
modules := make([]*moduleMeta, 0, len(m))
|
|
for _, module := range m {
|
|
modules = append(modules, module)
|
|
}
|
|
sort.SliceStable(modules, func(i, j int) bool {
|
|
return modules[i].Path < modules[j].Path
|
|
})
|
|
for _, module := range modules {
|
|
sort.SliceStable(module.Vulns, func(i, j int) bool {
|
|
return module.Vulns[i].ID < module.Vulns[j].ID
|
|
})
|
|
}
|
|
return json.Marshal(modules)
|
|
}
|