1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
|
// Copyright 2022 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 govulncheck provides functionality to support the govulncheck command.
package govulncheck
import (
"fmt"
"go/token"
"strings"
"golang.org/x/tools/go/packages"
"golang.org/x/vuln/client"
"golang.org/x/vuln/osv"
)
// LoadMode is the level of information needed for each package
// for running golang.org/x/tools/go/packages.Load.
var LoadMode = packages.NeedName | packages.NeedImports | packages.NeedTypes |
packages.NeedSyntax | packages.NeedTypesInfo | packages.NeedDeps |
packages.NeedModule
// Config is used for configuring the output of govulncheck.
type Config struct {
// Client is the client used to make requests to a vulnerability
// database(s). If nil, a default client is constructed that makes requests
// to vuln.go.dev.
Client client.Client
// GoVersion specifies the Go version used when analyzing source code.
//
// By default, GoVersion is the go command version found from the PATH.
GoVersion string
}
// Result is the result of executing Source or Binary.
type Result struct {
// Vulns contains all vulnerabilities that are called or imported by
// the analyzed module.
Vulns []*Vuln
}
// Vuln represents a single OSV entry.
type Vuln struct {
// OSV contains all data from the OSV entry for this vulnerability.
OSV *osv.Entry
// Modules contains all of the modules in the OSV entry where a
// vulnerable package is imported by the target source code or binary.
//
// For example, a module M with two packages M/p1 and M/p2, where only p1
// is vulnerable, will appear in this list if and only if p1 is imported by
// the target source code or binary.
Modules []*Module
}
// IsCalled reports whether the vulnerability is called, therefore
// affecting the target source code or binary.
//
// TODO: add unit tests
func (v *Vuln) IsCalled() bool {
for _, m := range v.Modules {
for _, p := range m.Packages {
if len(p.CallStacks) > 0 {
return true
}
}
}
return false
}
// Module represents a specific vulnerability relevant to a single module.
type Module struct {
// Path is the module path of the module containing the vulnerability.
//
// Importable packages in the standard library will have the path "stdlib".
Path string
// FoundVersion is the module version where the vulnerability was found.
FoundVersion string
// FixedVersion is the module version where the vulnerability was
// fixed. If there are multiple fixed versions in the OSV report, this will
// be the latest fixed version.
//
// This is empty if a fix is not available.
FixedVersion string
// Packages contains all the vulnerable packages in OSV entry that are
// imported by the target source code or binary.
//
// For example, given a module M with two packages M/p1 and M/p2, where
// both p1 and p2 are vulnerable, p1 and p2 will each only appear in this
// list they are individually imported by the target source code or binary.
Packages []*Package
}
// Package is a Go package with known vulnerable symbols.
type Package struct {
// Path is the import path of the package containing the vulnerability.
Path string
// CallStacks contains a representative call stack for each
// vulnerable symbol that is called.
//
// For vulnerabilities found from binary analysis, only CallStack.Symbol
// will be provided.
//
// For non-affecting vulnerabilities reported from the source mode
// analysis, this will be empty.
CallStacks []CallStack
}
// CallStacks contains a representative call stack for a vulnerable
// symbol.
type CallStack struct {
// Symbol is the name of the detected vulnerable function
// or method.
//
// This follows the naming convention in the OSV report.
Symbol string
// Summary is a one-line description of the callstack, used by the
// default govulncheck mode.
//
// Example: module3.main calls github.com/shiyanhui/dht.DHT.Run
Summary string
// Frames contains an entry for each stack in the call stack.
//
// Frames are sorted starting from the entry point to the
// imported vulnerable symbol. The last frame in Frames should match
// Symbol.
Frames []*StackFrame
}
// StackFrame represents a call stack entry.
type StackFrame struct {
// PackagePath is the import path.
PkgPath string
// FuncName is the function name.
FuncName string
// RecvType is the fully qualified receiver type,
// if the called symbol is a method.
//
// The client can create the final symbol name by
// prepending RecvType to FuncName.
RecvType string
// Position describes an arbitrary source position
// including the file, line, and column location.
// A Position is valid if the line number is > 0.
Position token.Position
}
// Name returns the full qualified function name from sf,
// adjusted to remove pointer annotations.
func (sf *StackFrame) Name() string {
var n string
if sf.RecvType == "" {
n = fmt.Sprintf("%s.%s", sf.PkgPath, sf.FuncName)
} else {
n = fmt.Sprintf("%s.%s", sf.RecvType, sf.FuncName)
}
return strings.TrimPrefix(n, "*")
}
// Pos returns the position of the call in sf as string.
// If position is not available, return "".
func (sf *StackFrame) Pos() string {
if sf.Position.IsValid() {
return sf.Position.String()
}
return ""
}
|