Documentation
¶
Overview ¶
Package engine defines what a detector is and runs detectors over a target.
The engine reads each target once and hands every file to each detector that supports that kind of target. Detectors decide verdicts. The engine decides nothing about any vulnerability itself, but it does enforce one rule for every detector: a finding can only be cleared (fixed, inactive or managed) with a reason attached.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type CVEResult ¶
type CVEResult struct {
ID string `json:"id"`
Verdict Verdict `json:"verdict"`
Reason string `json:"reason,omitempty"`
}
CVEResult is one CVE's verdict inside a finding that covers several.
type Detector ¶
type Detector interface {
Manifest() Manifest
// Load parses and checks the detector's embedded data. An error means the
// data contradicts itself and the engine refuses to run.
Load() error
// NewScan starts a scan of one filesystem or image target.
NewScan(kind TargetKind) Scan
}
Detector is a detector registered with the engine.
type File ¶
type File struct {
Path string
Data []byte
Executable bool
// Member is true for a file found inside an archive or package.
Member bool
}
File is one file handed to a detector. Path is absolute within the target; archive members are "outer!/inner".
type Finding ¶
type Finding struct {
Detector string `json:"detector"`
Kind string `json:"kind"`
Path string `json:"path"`
Verdict Verdict `json:"verdict"`
Reason string `json:"reason,omitempty"`
// Message is the exact fact, in words.
Message string `json:"message"`
// Method says how it was found (pem, pkcs12, go-buildinfo, elf-strings...).
Method string `json:"method,omitempty"`
// Facts are short checkable values (hashes, versions), also written to SARIF.
Facts map[string]string `json:"facts,omitempty"`
CVEs []CVEResult `json:"cves,omitempty"`
Fix string `json:"fix,omitempty"`
// Details is the detector's own record of the finding, kept whole.
Details any `json:"details,omitempty"`
}
Finding is one proven fact about a target.
type Kind ¶
type Kind struct {
ID string // stable, used in SARIF rule IDs as "<detector>/<kind>"
Title string
// Level is the SARIF level for a vulnerable finding: "error" or "warning".
Level string
}
Kind is one type of finding a detector reports.
type Manifest ¶
type Manifest struct {
ID string
Title string
CVEs []string
Advisories []string // URLs; the first is the SARIF help link
Disclosed string // YYYY-MM-DD
Targets []TargetKind
Kinds []Kind
Tags []string
// Archives asks the engine to unpack archives and packages (jar, whl, deb,
// rpm, compressed files, PyInstaller executables) and hand every member to
// Visit as "outer!/inner".
Archives bool
// Data identifies the detector's knowledge snapshot, for the report.
Data string
}
Manifest describes a detector.
func (Manifest) Supports ¶
func (m Manifest) Supports(kind TargetKind) bool
Supports reports whether the detector runs on kind.
type Options ¶
type Options struct {
MaxFileSize int64
Platform string // image platform, e.g. linux/amd64
AsRoot bool // fs: treat the directory as a system root
Timeout time.Duration // host: connect timeout
}
Options control a run.
type Prober ¶
type Prober interface {
// Probe connects to addr and returns the name it resolved to, how many items
// it checked (certificates, responses) and what it found.
Probe(ctx context.Context, addr string, timeout time.Duration) (target string, checked int, findings []Finding, err error)
}
Prober is implemented by detectors that check live network hosts.
type Reader ¶
Reader is implemented by detectors that only need some files read in full. A detector without it receives every file.
type Scan ¶
type Scan interface {
Visit(f File) []Skip
Finish(ctx TargetContext) []Finding
}
Scan is one detector's work on one target. Visit sees every file the engine reads; a detector keeps the few file contents its verdicts need. Finish runs once, after the last file.
type Target ¶
type Target struct {
Name string `json:"target"`
Type TargetKind `json:"type"`
Digest string `json:"digest,omitempty"`
Platform string `json:"platform,omitempty"`
Root string `json:"root,omitempty"` // filesystem scans: SARIF paths are relative to it
Files int `json:"files_scanned"`
Findings []Finding `json:"findings"`
Skipped []source.Skip `json:"skipped"`
Error string `json:"error,omitempty"`
}
Target is one scanned thing: a directory, an image or a server.
func ScanFS ¶
ScanFS scans a directory or file. With AsRoot (always for "/"), the directory is treated as a system root, for example a host mounted at /host or an extracted image, and paths are reported inside it. Otherwise paths are the real absolute paths, so location rules see /etc/ssl/... even when scanning /etc/ssl.
func ScanHost ¶
ScanHost runs every detector that probes live hosts against addr (host, host:port or a URL).
func ScanImage ¶
ScanImage scans a container image: a registry reference, docker-archive:FILE (from docker save), or rootfs:FILE / rootfs:- (a flat filesystem tar from docker export).
type TargetContext ¶
type TargetContext interface {
Kind() TargetKind
// Exists reports whether a regular file at that absolute path was scanned.
Exists(path string) bool
// Env is the image configuration's environment ("KEY=value"), nil otherwise.
Env() []string
// Aliases returns every path that names the same file as p (symlinks, hard
// links), p included.
Aliases(p string) []string
}
TargetContext is what a detector can ask about the rest of the target when it decides verdicts.
type TargetKind ¶
type TargetKind string
TargetKind is a kind of thing the engine scans.
const ( Filesystem TargetKind = "filesystem" Image TargetKind = "image" Host TargetKind = "host" )
type Verdict ¶
type Verdict string
Verdict is a finding's outcome.
const ( // Vulnerable: proven exposed. Vulnerable Verdict = "vulnerable" // Unknown: the evidence does not settle it. The reason says what to check. Unknown Verdict = "unknown" // Fixed: proven to have the fix. Fixed Verdict = "fixed" // Inactive: present but provably not used. Inactive Verdict = "inactive" // Managed: another layer decides (an OS keychain, a browser's blocklist). // Listed, not counted. Managed Verdict = "managed" )