blob: 0e94cb96a150d02cef7be442742f12f5ad83ecd8 [file] [log] [blame]
// Copyright 2024 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 report
import (
"context"
"golang.org/x/vulndb/internal/cveclient"
"golang.org/x/vulndb/internal/cveschema"
"golang.org/x/vulndb/internal/cveschema5"
"golang.org/x/vulndb/internal/ghsa"
"golang.org/x/vulndb/internal/proxy"
)
// Source represents a vulnerability format (e.g., GHSA, CVE)
// that can be converted to our Report format.
type Source interface {
// SourceID returns the ID of the source.
// For example, the GHSA or CVE id.
SourceID() string
ToReport(modulePath string) *Report
}
func New(src Source, goID string, modulePath string, pc *proxy.Client) *Report {
r := src.ToReport(modulePath)
r.ID = goID
r.SourceMeta = &SourceMeta{
ID: src.SourceID(),
}
r.Fix(pc)
return r
}
type Fetcher interface {
Fetch(ctx context.Context, id string) (Source, error)
}
type cve5 struct {
*cveschema5.CVERecord
}
var _ Source = &cve5{}
func ToCVE5(c *cveschema5.CVERecord) Source {
return &cve5{CVERecord: c}
}
func (c *cve5) ToReport(modulePath string) *Report {
return cve5ToReport(c.CVERecord, modulePath)
}
func (c *cve5) SourceID() string {
return c.Metadata.ID
}
type cve5Fetcher struct{}
func CVE5Fetcher() Fetcher {
return &cve5Fetcher{}
}
func (_ *cve5Fetcher) Fetch(ctx context.Context, id string) (Source, error) {
cve, err := cveclient.Fetch(id)
if err != nil {
return nil, err
}
return &cve5{CVERecord: cve}, nil
}
// cve4 is a wrapper for a CVE in CVE JSON 4.0 (legacy) format.
//
// Note: Fetch is not implemented for CVE4, as it is a legacy format
// which will be phased out soon.
type cve4 struct {
*cveschema.CVE
}
var _ Source = &cve4{}
func ToCVE4(c *cveschema.CVE) Source {
return &cve4{CVE: c}
}
func (c *cve4) ToReport(modulePath string) *Report {
return cveToReport(c.CVE, modulePath)
}
func (c *cve4) SourceID() string {
return c.ID
}
// legacyGHSA is a wrapper for a GHSA in the format retrievable
// via the Github GraphQL API.
//
// We are planning to phase this out in favor of the Github OSV format,
// but some of our processes still rely on this format.
type legacyGHSA struct {
*ghsa.SecurityAdvisory
}
var _ Source = &legacyGHSA{}
func ToLegacyGHSA(g *ghsa.SecurityAdvisory) Source {
return &legacyGHSA{
SecurityAdvisory: g,
}
}
func (g *legacyGHSA) ToReport(modulePath string) *Report {
return ghsaToReport(g.SecurityAdvisory, modulePath)
}
func (g *legacyGHSA) SourceID() string {
return g.ID
}
type legacyGHSAFetcher struct {
*ghsa.Client
}
func LegacyGHSAFetcher(c *ghsa.Client) Fetcher {
return &legacyGHSAFetcher{
Client: c,
}
}
func (g *legacyGHSAFetcher) Fetch(ctx context.Context, id string) (Source, error) {
fetched, err := g.FetchGHSA(ctx, id)
if err != nil {
return nil, err
}
return &legacyGHSA{
SecurityAdvisory: fetched,
}, err
}
// original represents an original report created from scratch by the Go Security Team.
//
// This is used for standard library & toolchain reports, or in cases where the
// source report cannot be retrieved automatically.
type original struct{}
var _ Source = &original{}
func Original() Source {
return &original{}
}
func (original) ToReport(modulePath string) *Report {
return &Report{
Modules: []*Module{
{
Module: modulePath,
},
},
}
}
func (original) SourceID() string {
return sourceGoTeam
}