blob: 02b595301a29c03268774228033ee6e7f8888cab [file] [log] [blame]
// 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 genericosv
import (
"fmt"
"strings"
"golang.org/x/vulndb/internal/idstr"
"golang.org/x/vulndb/internal/osv"
"golang.org/x/vulndb/internal/proxy"
"golang.org/x/vulndb/internal/report"
)
var _ report.Source = &Entry{}
// ToReport converts OSV into a Go Report with the given ID.
func (e *Entry) ToReport(*proxy.Client, string) *report.Report {
r := &report.Report{
Summary: report.Summary(e.Summary),
Description: report.Description(e.Details),
}
addAlias := func(alias string) {
switch {
case idstr.IsCVE(alias):
r.CVEs = append(r.CVEs, alias)
case idstr.IsGHSA(alias):
r.GHSAs = append(r.GHSAs, alias)
case idstr.IsGoID(alias):
// ignore Go IDs
default:
r.UnknownAliases = append(r.UnknownAliases, alias)
}
}
addAlias(e.ID)
for _, alias := range e.Aliases {
addAlias(alias)
}
r.Modules = affectedToModules(e.Affected)
for _, ref := range e.References {
r.References = append(r.References, convertRef(ref))
}
r.Credits = convertCredits(e.Credits)
if e.IsWithdrawn() {
r.Withdrawn = &osv.Time{Time: e.Withdrawn}
}
return r
}
func (osv *Entry) SourceID() string {
return osv.ID
}
func affectedToModules(as []Affected) []*report.Module {
var modules []*report.Module
for _, a := range as {
if a.Package.Ecosystem != EcosystemGo {
continue
}
versions, unsupportedVersions := convertVersions(a.Ranges)
modules = append(modules, &report.Module{
Module: a.Package.Name,
Versions: versions,
UnsupportedVersions: unsupportedVersions,
})
}
return modules
}
func convertVersions(rs []Range) (vs report.Versions, unsupported report.Versions) {
for _, r := range rs {
for _, e := range r.Events {
if e.Introduced != "" || e.Fixed != "" {
var vr *report.Version
switch {
case e.Introduced == "0":
continue
case e.Introduced != "":
vr = report.Introduced(e.Introduced)
case e.Fixed != "":
vr = report.Fixed(e.Fixed)
}
vs = append(vs, vr)
continue
}
uv := new(report.Version)
switch {
case e.LastAffected != "":
uv.Version = e.LastAffected
uv.Type = "last_affected"
case e.Limit != "":
uv.Version = e.Limit
uv.Type = "limit"
default:
uv.Version = fmt.Sprint(e)
uv.Type = "unknown"
}
unsupported = append(unsupported, uv)
}
}
return vs, unsupported
}
func convertRef(ref Reference) *report.Reference {
return &report.Reference{
Type: osv.ReferenceType(ref.Type),
URL: ref.URL,
}
}
func convertCredits(cs []Credit) []string {
var credits []string
for _, c := range cs {
credit := c.Name
if len(c.Contact) != 0 {
credit = fmt.Sprintf("%s (%s)", c.Name, strings.Join(c.Contact, ","))
}
credits = append(credits, credit)
}
return credits
}