blob: aae3a0b27cf8b596d060dffffef15fb4b8a9c1c2 [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 main
import (
"context"
"fmt"
vlog "golang.org/x/vulndb/cmd/vulnreport/log"
"golang.org/x/vulndb/internal/cve5"
"golang.org/x/vulndb/internal/genericosv"
"golang.org/x/vulndb/internal/pkgsite"
"golang.org/x/vulndb/internal/report"
"golang.org/x/vulndb/internal/triage"
)
type triager interface {
triage(context.Context, string) error
}
type cveTriager struct {
report.Fetcher
pc *pkgsite.Client
}
func (t *cveTriager) triage(ctx context.Context, id string) error {
cve, err := fetchAs[*cve5.CVERecord](ctx, t, id)
if err != nil {
return err
}
result, err := triage.RefersToGoModule(ctx, cve, t.pc)
if err != nil {
return err
}
printResult(id, result)
return nil
}
type ghsaTriager struct {
report.Fetcher
}
func (t *ghsaTriager) triage(ctx context.Context, id string) error {
ghsa, err := fetchAs[*genericosv.Entry](ctx, t, id)
if err != nil {
return err
}
result := triage.ContainsGoModule(ghsa)
printResult(id, result)
return nil
}
func printResult(id string, result *triage.Result) {
if result == nil {
vlog.Infof("%s does not appear to be a Go vulnerability", id)
return
}
vlog.Outf("%s is likely a Go vulnerability", id)
if result.ModulePath != "" {
vlog.Outf("Module: %s", result.ModulePath)
}
if result.PackagePath != "" {
vlog.Outf("Package: %s", result.PackagePath)
}
if result.Reason != "" {
vlog.Outf("Reason: %s", result.Reason)
}
}
func fetchAs[T any](ctx context.Context, f report.Fetcher, id string) (T, error) {
var zero T
src, err := f.Fetch(ctx, id)
if err != nil {
return zero, err
}
v, ok := src.(T)
if !ok {
return zero, fmt.Errorf("%s cannot be cast as %T", src, zero)
}
return v, nil
}
func triageCVEs(ctx context.Context, cves []string) {
if len(cves) == 0 {
return
}
t := &cveTriager{Fetcher: cve5.NewFetcher(), pc: pkgsite.Default()}
triageBatch(ctx, t, cves)
}
func triageGHSAs(ctx context.Context, ghsas []string) {
if len(ghsas) == 0 {
return
}
t := &ghsaTriager{Fetcher: genericosv.NewFetcher()}
triageBatch(ctx, t, ghsas)
}
func triageBatch(ctx context.Context, t triager, ids []string) {
for _, id := range ids {
if err := t.triage(ctx, id); err != nil {
vlog.Err(err)
}
}
}