vulncheck

package
v0.0.0-...-4eb9d72 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 31, 2023 License: BSD-3-Clause Imports: 27 Imported by: 0

Documentation

Overview

Package vulncheck detects uses of known vulnerabilities in Go programs.

Vulncheck identifies vulnerability uses in Go programs at the level of call graph, package import graph, and module requires graph. For instance, vulncheck identifies which vulnerable functions and methods are transitively called from the program entry points. vulncheck also detects transitively imported packages and required modules that contain known vulnerable functions and methods.

We recommend using the command line tool govulncheck to detect vulnerabilities in your code.

Usage

The two main APIs of vulncheck, Source and Binary, allow vulnerability detection in Go source code and binaries, respectively.

Source accepts a list of Package objects, which are a trimmed version of golang.org/x/tools/go/packages.Package objects to reduce memory consumption. Binary accepts a path to a Go binary file that must have been compiled with Go 1.18 or greater.

Both Source and Binary require information about known vulnerabilities in the form of a vulnerability database, specifically a github.com/julieqiu/vuln/internal/client.Client. The vulnerabilities are modeled using the github.com/julieqiu/vuln/osv format.

Results

The results of vulncheck are slices of the call graph, package imports graph, and module requires graph leading to the use of an identified vulnerability. The parts of these graphs not related to any vulnerabilities are omitted.

The CallStacks and ImportChains functions search the returned slices for user-friendly representative call stacks and import chains. These call stacks and import chains are provided as examples of vulnerability uses in the client code.

Limitations

There are some limitations with vulncheck. Please see the documented limitations for more information.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CallStacks

func CallStacks(res *Result) map[*Vuln][]CallStack

CallStacks returns representative call stacks for each vulnerability in res. The returned call stacks are heuristically ordered by how seemingly easy is to understand them: shorter call stacks with less dynamic call sites appear earlier in the returned slices.

CallStacks performs a breadth-first search of res.CallGraph starting at the vulnerable symbol and going up until reaching an entry function or method in res.CallGraph.Entries. During this search, each function is visited at most once to avoid potential exponential explosion. Hence, not all call stacks are analyzed.

func ImportChains

func ImportChains(res *Result) map[*Vuln][]ImportChain

ImportChains returns a slice of representative import chains for each vulnerability in res. The returned chains are ordered increasingly by their length.

ImportChains performs a breadth-first search of res.RequireGraph starting at a vulnerable package and going up until reaching an entry package in res.ImportGraph.Entries. During this search, a package is visited only once to avoid analyzing every possible import chain. Hence, not all import chains are analyzed.

Note that vulnerabilities from the same package will have the same slice of identified import chains.

Types

type CallGraph

type CallGraph struct {
	// Functions contains all call graph nodes as a map: FuncNode.ID -> FuncNode.
	Functions map[int]*FuncNode

	// Entries are IDs of a subset of Functions representing vulncheck entry points.
	Entries []int
}

CallGraph is a slice of a full program call graph whose sinks are vulnerable functions and sources are entry points of user packages.

CallGraph is directed from vulnerable functions towards program entry functions (see FuncNode) for a more efficient traversal of the slice related to a particular vulnerability.

type CallSite

type CallSite struct {
	// Parent is ID of the enclosing function where the call is made.
	Parent int

	// Name stands for the name of the function (variable) being called.
	Name string

	// RecvType is the full path of the receiver object type, if any.
	RecvType string

	// Position describes the position of the function in the file.
	Pos *token.Position

	// Resolved indicates if the called function can be statically resolved.
	Resolved bool
}

A CallSite describes a function call.

type CallStack

type CallStack []StackEntry

CallStack is a call stack starting with a client function or method and ending with a call to a vulnerable symbol.

type Config

type Config struct {
	// ImportsOnly instructs vulncheck to analyze import chains only.
	// Otherwise, call chains are analyzed too.
	ImportsOnly bool

	// Client is used for querying data from a vulnerability database.
	Client client.Client

	// SourceGoVersion is Go version used to build Source inputs passed
	// to vulncheck. If not provided, the current Go version at PATH
	// is used to detect vulnerabilities in Go standard library.
	SourceGoVersion string

	// Consider only vulnerabilities that apply to this OS and architecture.
	// An empty string means "all" (don't filter).
	// Applies only to Source.
	GOOS, GOARCH string
}

Config is used for configuring vulncheck algorithms.

type FuncNode

type FuncNode struct {
	// ID is the id used to identify the FuncNode in CallGraph.
	ID int

	// Name is the name of the function.
	Name string

	// RecvType is the receiver object type of this function, if any.
	RecvType string

	// PkgPath is the import path of the package containing the function.
	PkgPath string

	// Position describes the position of the function in the file.
	Pos *token.Position

	// CallSites is a set of call sites where this function is called.
	CallSites []*CallSite
}

A FuncNode describes a function in the call graph.

func (*FuncNode) String

func (fn *FuncNode) String() string

type ImportChain

type ImportChain []*PkgNode

ImportChain is a slice of packages where each subsequent package is imported by its immediate predecessor. The chain starts with a client package and ends in a package with some known vulnerabilities.

type ImportGraph

type ImportGraph struct {
	// Packages contains all package nodes as a map: package node id -> package node.
	Packages map[int]*PkgNode

	// Entries are IDs of a subset of Packages representing packages of vulncheck entry points.
	Entries []int
}

ImportGraph is a slice of a full program package import graph whose sinks are packages with some known vulnerabilities and sources are user specified packages.

ImportGraph is directed from a vulnerable package towards the program entry packages (see PkgNode) for a more efficient traversal of the slice related to a particular vulnerability.

type ModNode

type ModNode struct {
	// ID is the id used to identify the ModNode in CallGraph.
	ID int

	// Path is the module path.
	Path string

	// Version is the module version.
	Version string

	// Replace is the ID of the replacement module node.
	// A zero value means there is no replacement.
	Replace int

	// RequiredBy contains IDs of the modules requiring this module.
	RequiredBy []int
}

A ModNode describes a module in the requires graph.

type Module

type Module struct {
	Path    string
	Version string
	Dir     string
	Replace *Module
}

Module is a Go module for vulncheck analysis.

type Package

type Package struct {
	Name      string
	PkgPath   string
	Imports   []*Package
	Pkg       *types.Package
	Fset      *token.FileSet
	Syntax    []*ast.File
	TypesInfo *types.Info
	Module    *Module
}

Package is a Go package for vulncheck analysis. It is a version of packages.Package trimmed down to reduce memory consumption.

func Convert

func Convert(pkgs []*packages.Package) []*Package

Convert transforms a slice of packages.Package to a slice of corresponding vulncheck.Package.

type PkgNode

type PkgNode struct {
	// ID is the id used to identify the PkgNode in ImportGraph.
	ID int

	// Name is the package identifier as it appears in the source code.
	Name string

	// Path is the package path.
	Path string

	// Module holds ID of the corresponding module (node) in the Requires graph.
	Module int

	// ImportedBy contains IDs of packages directly importing this package.
	ImportedBy []int
	// contains filtered or unexported fields
}

A PkgNode describes a package in the import graph.

type RequireGraph

type RequireGraph struct {
	// Modules contains all module nodes as a map: module node id -> module node.
	Modules map[int]*ModNode

	// Entries are IDs of a subset of Modules representing modules of vulncheck entry points.
	Entries []int
}

RequireGraph is a slice of a full program module requires graph whose sinks are modules with known vulnerabilities and sources are modules of user entry packages.

RequireGraph is directed from a vulnerable module towards the program entry modules (see ModNode) for a more efficient traversal of the slice related to a particular vulnerability.

type Result

type Result struct {
	// Calls is a call graph whose roots are program entry functions and
	// methods, and sinks are known vulnerable symbols. It is empty when
	// Config.ImportsOnly is true or when no vulnerable symbols are reachable
	// via the program call graph.
	Calls *CallGraph

	// Imports is a package dependency graph whose roots are entry user packages
	// and sinks are packages with some known vulnerable symbols. It is empty
	// when no packages with vulnerabilities are imported in the program.
	Imports *ImportGraph

	// Requires is a module dependency graph whose roots are entry user modules
	// and sinks are modules with some vulnerable packages. It is empty when no
	// modules with vulnerabilities are required by the program. If used, the
	// standard library is modeled as an artificial "stdlib" module whose version
	// is the Go version used to build the code under analysis.
	Requires *RequireGraph

	// Vulns contains information on detected vulnerabilities and their place in
	// the above graphs. Only vulnerabilities whose symbols are reachable in Calls,
	// or whose packages are imported in Imports, or whose modules are required in
	// Requires, have an entry in Vulns.
	Vulns []*Vuln

	// Modules are the modules that comprise the user code.
	Modules []*Module
}

Result contains information on how known vulnerabilities are reachable in the call graph, package imports graph, and module requires graph of the user code.

func Binary

func Binary(ctx context.Context, exe io.ReaderAt, cfg *Config) (_ *Result, err error)

Binary detects presence of vulnerable symbols in exe. The Calls, Imports, and Requires fields on Result will be empty.

func Source

func Source(ctx context.Context, pkgs []*Package, cfg *Config) (_ *Result, err error)

Source detects vulnerabilities in packages. The result will contain:

1) An ImportGraph related to an import of a package with some known vulnerabilities.

2) A RequireGraph related to a require of a module with a package that has some known vulnerabilities.

3) A CallGraph leading to the use of a known vulnerable function or method.

type StackEntry

type StackEntry struct {
	// Function whose frame is on the stack.
	Function *FuncNode

	// Call is the call site inducing the next stack frame.
	// nil when the frame represents the last frame in the stack.
	Call *CallSite
}

StackEntry is an element of a call stack.

type Vuln

type Vuln struct {
	// OSV contains information on the detected vulnerability in the shared
	// vulnerability format.
	//
	// OSV, Symbol, PkgPath, and ModPath identify a vulnerability.
	//
	// Note that *osv.Entry may describe multiple symbols from multiple
	// packages.
	OSV *osv.Entry

	// Symbol is the name of the detected vulnerable function or method.
	Symbol string

	// PkgPath is the package path of the detected Symbol.
	PkgPath string

	// ModPath is the module path corresponding to PkgPath.
	ModPath string

	// CallSink is the ID of the FuncNode in Result.Calls corresponding to
	// Symbol.
	//
	// When analyzing binaries, Symbol is not reachable, or Config.ImportsOnly
	// is true, CallSink will be unavailable and set to 0.
	CallSink int

	// ImportSink is the ID of the PkgNode in Result.Imports corresponding to
	// PkgPath.
	//
	// When analyzing binaries or PkgPath is not imported, ImportSink will be
	// unavailable and set to 0.
	ImportSink int

	// RequireSink is the ID of the ModNode in Result.Requires corresponding to
	// ModPath.
	//
	// When analyzing binaries, RequireSink will be unavailable and set to 0.
	RequireSink int
}

Vuln provides information on how a vulnerability is affecting user code by connecting it to the Result.{Calls,Imports,Requires} graphs. Vulnerabilities detected in Go binaries do not appear in the Result graphs.

Directories

Path Synopsis
internal
gosym
Package gosym implements access to the Go symbol and line number tables embedded in Go binaries generated by the gc compilers.
Package gosym implements access to the Go symbol and line number tables embedded in Go binaries generated by the gc compilers.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL