scan

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Oct 13, 2026 License: MPL-2.0 Imports: 21 Imported by: 0

Documentation

Overview

Package scan orchestrates external vulnerability scanners over stored SBOM package inventories. Dufflebag never scans in-process and never owns a vulnerability feed; this package translates purls into provider queries and reports attributed findings.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Classify

func Classify(purl string) (Class, *Query, string)

Classify maps one purl to its class and, when queryable, the ecosystem-form query to issue. The reason string explains every non-queryable class.

func RecordedOSVStubFixtures

func RecordedOSVStubFixtures() map[OSVStubRoute][]byte

RecordedOSVStubFixtures returns an independent copy of the recorded response set. Callers may mutate the copy to exercise failure modes.

func Worse added in v0.4.2

func Worse(a, b Severity) bool

Worse reports whether a ranks above b on the display scale.

func WorstSeverityValue

func WorstSeverityValue(values []SeverityValue) string

WorstSeverityValue returns the provider's verbatim value for the worst normalised severity. It is used by read projections that need both the fixed display band and the original provider value.

Types

type Attribution

type Attribution struct {
	Adapter          string
	Engine           string
	DatabaseRevision string
	ObservedAt       time.Time
}

type Class

type Class string

Class is the deterministic pre-query classification of an SBOM package purl. Classification runs before any network traffic: OSV answers {} for both "supported, zero findings" and "ecosystem not covered", so coverage can only be asserted here, never inferred from a response.

const (
	ClassQueryable   Class = "queryable"
	ClassEmpty       Class = "empty"
	ClassInvalid     Class = "invalid"
	ClassUnversioned Class = "unversioned"
	ClassUnsupported Class = "unsupported"
)

type Coverage

type Coverage struct {
	Submitted   int
	Empty       int
	Invalid     int
	Unversioned int
	Unsupported int
}

Coverage reports what happened to every inventory package before any wire traffic: only Submitted packages were queried. Unsupported is a first-class state because the provider's empty answer is indistinguishable from supported-with-zero-findings (spike duf-o0ou.1).

type Finding

type Finding struct {
	Package   Package
	ID        string
	Summary   string
	Aliases   []string
	Related   []string
	Published time.Time
	Modified  time.Time
	// Withdrawn is zero unless the provider withdrew the advisory.
	Withdrawn time.Time
	// FixedVersions holds every distinct fixed version the matching ranges
	// supply, sorted lexicographically; empty means no fix is available.
	FixedVersions []string
	Severities    []SeverityValue
	Severity      Severity
}

type Health

type Health struct {
	OK         bool
	Latency    time.Duration
	Detail     string
	ObservedAt time.Time
}

type Inventory

type Inventory struct {
	Packages []Package
}

type OSV

type OSV struct {
	// contains filtered or unexported fields
}

OSV queries api.osv.dev (or a stand-in) for vulnerability findings. All HTTP goes through the configured client; the clock stamps attribution and probe observations and resolves Retry-After dates so tests inject a fake.

func NewOSV

func NewOSV(base string, client *http.Client, clock func() time.Time) *OSV

func (*OSV) Probe

func (o *OSV) Probe(ctx context.Context) (Health, error)

Probe answers whether the provider serves the batch endpoint: an empty querybatch exercises the real POST path at minimal cost.

func (*OSV) Scan

func (o *OSV) Scan(ctx context.Context, inv Inventory) (Result, error)

type OSVStub

type OSVStub struct {
	// contains filtered or unexported fields
}

OSVStub serves the recorded api.osv.dev captures without decoding or re-encoding their response bodies.

func NewOSVStub

func NewOSVStub(responses map[OSVStubRoute][]byte) *OSVStub

NewOSVStub constructs a handler from responses. A nil response map selects the complete recorded fixture set.

func (*OSVStub) Requests

func (s *OSVStub) Requests() []OSVStubRequest

Requests returns a snapshot of every request received by the stub.

func (*OSVStub) ServeHTTP

func (s *OSVStub) ServeHTTP(w http.ResponseWriter, r *http.Request)

type OSVStubRequest

type OSVStubRequest struct {
	Method string
	Path   string
	Body   []byte
	Status int
}

OSVStubRequest is one request observed by OSVStub.

type OSVStubRoute

type OSVStubRoute struct {
	Method string
	Path   string
	Body   string
}

OSVStubRoute identifies one request the recorded OSV stub recognises. POST bodies are matched exactly so an adapter wire-shape change fails loudly.

type Package

type Package struct {
	SBOMID  string
	Name    string
	Version string
	Purl    string
}

Package is the full sbom_packages identity a finding attaches to.

type Query

type Query struct {
	Ecosystem string
	Name      string
	Version   string
	// RedHatMajor carries the enterprise_linux major from the purl's distro
	// qualifier (rhel-9.8 -> "9"). Set only for Ecosystem "Red Hat", where the
	// adapter's phase-2 stream confirmation needs it; empty otherwise.
	RedHatMajor string
}

Query is the OSV ecosystem-form query a queryable purl translates to. Purl-form queries are never issued: Alpine purl matching returns nothing at all, deb/rpm purl matching evaluates every distribution stream, and rpm epochs ride in a qualifier the purl form ignores (spike duf-o0ou.1, testdata/spike-manifest.json).

type Result

type Result struct {
	Attribution Attribution
	Coverage    Coverage
	Findings    []Finding
	Transcript  Transcript
}

type Scanner

type Scanner interface {
	Scan(ctx context.Context, inv Inventory) (Result, error)
	Probe(ctx context.Context) (Health, error)
}

Scanner is the seam between the reconciler and an external scanner service. Scan is all-or-nothing: any partial provider failure returns an error, and Findings are usable only when the error is nil. Result always carries the attribution and the final provider response to every request, even alongside an error, so a failed run still leaves an auditable transcript.

type Severity

type Severity string

Severity is the derived fixed display scale, computed for rollups only.

const (
	SeverityUnknown    Severity = "unknown"
	SeverityNegligible Severity = "negligible"
	SeverityLow        Severity = "low"
	SeverityMedium     Severity = "medium"
	SeverityHigh       Severity = "high"
	SeverityCritical   Severity = "critical"
)

type SeverityValue

type SeverityValue struct {
	// Source records where in the provider payload the value came from:
	// "osv" (severity[]), "osv:database_specific", "osv:ecosystem_specific".
	Source string
	// Type is the provider's type label: CVSS_V2/CVSS_V3/CVSS_V4 for vectors,
	// "label" for qualitative labels, "urgency" for Debian urgency.
	Type  string
	Value string
}

SeverityValue is one provider-supplied severity, verbatim.

type Transcript

type Transcript struct {
	Records [][]byte
}

Transcript holds provider response bodies in the adapter's canonical order. Encode length-prefixes each record with an 8-byte big-endian byte count; Digest is SHA-256 over exactly that encoding.

func (Transcript) Digest

func (t Transcript) Digest() string

func (Transcript) Encode

func (t Transcript) Encode() []byte

Jump to

Keyboard shortcuts

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