| // 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 |
| } |