advisorysource

package
v0.0.0-...-c2055b0 Latest Latest
Warning

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

Go to latest
Published: Jul 31, 2026 License: Apache-2.0 Imports: 22 Imported by: 0

Documentation

Overview

Package advisorysource defines Deputy's advisory-source seam: the abstraction over components that, given a set of packages, return known advisories (vulnerabilities and malware) affecting them.

A Source is any advisory provider: the built-in OSV source today, and external threat-feed or vendor plugins in the future. Every source implements the same contract and returns the same proto types (deputy.plugin.v1 and deputy.vulnerability.v1), so built-in and plugin sources are interchangeable; this mirrors how Deputy's inventory extractors achieve built-in/plugin parity.

A Registry aggregates sources: it routes each package only to sources whose declared [Capabilities] cover the package's ecosystem and artifact kind, runs them concurrently, merges findings with union-with-provenance semantics (a finding corroborated by several sources records each in Finding.sources), and reports coverage, including the (ecosystem, artifact) combinations no source could answer for, so callers can tell a genuinely clean result from an unqueried one instead of failing the whole scan.

Advisory records (the shared descriptions keyed by advisory ID) merge first-source-wins in registration order: when two sources return the same advisory ID with different record contents, the earlier-registered source's record is kept whole, with the built-in OSV source registered first by default. Provenance for who reported a finding lives on Finding.sources, not on the advisory record.

External sources are trusted components: a plugin subprocess runs with Deputy's operating-system privileges and a source's findings feed policy and remediation decisions verbatim, which is why sources only ever load by explicit opt-in (config file or DEPUTY_ADVISORY_SOURCES), never by PATH discovery.

Index

Constants

View Source
const EcosystemGitHubActions = "github-actions"

EcosystemGitHubActions is the canonical ecosystem label for GitHub Actions. OSV serves these from its advisory bucket, so it is a coverage label rather than an entry in the ecosystem registry.

View Source
const EnvAdvisorySources = "DEPUTY_ADVISORY_SOURCES"

EnvAdvisorySources names the environment variable listing advisory-source plugin programs to load, comma-separated (program names resolved via PATH, or absolute/relative paths). It is unioned with the config file's advisory_sources entries (see SetConfiguredSources). Loading is explicit opt-in: an advisory source can see and shape security findings, so Deputy never auto-executes binaries it merely finds on PATH.

View Source
const PluginProgramPrefix = "deputy-advisory-source-"

PluginProgramPrefix is the executable-name prefix Deputy discovers advisory source plugins by (e.g. "deputy-advisory-source-ghsa").

View Source
const SourceNameOSV = "osv"

SourceNameOSV is the provenance name recorded for OSV-derived findings.

Variables

This section is empty.

Functions

func DisableSubprocessSources

func DisableSubprocessSources()

DisableSubprocessSources excludes program-backed (subprocess) advisory sources from materialization for the rest of the process lifetime. Remote server mode must not execute code (see AGENTS.md), and source configs are process-global, reaching every scan a remote request triggers; the services layer calls this when constructing remote-mode handlers so a configured plugin binary or DEPUTY_ADVISORY_SOURCES entry can never execute. Each excluded source is reported through the materialization error, so the operator sees the reduced coverage instead of a silent gap. ConnectRPC (URL) sources are unaffected. There is deliberately no way to re-enable.

func DiscoverPluginPrograms

func DiscoverPluginPrograms() ([]string, error)

DiscoverPluginPrograms returns advisory-source plugin program names found on PATH (executables named deputy-advisory-source-*). Discovery only *lists* candidates (for example for a future "deputy plugins list" UX); it never executes them. To actually load a source, name it explicitly in DEPUTY_ADVISORY_SOURCES; auto-running discovered binaries would let a dropped executable forge or suppress findings.

func SetConfiguredSources

func SetConfiguredSources(cfgs []SourceConfig)

SetConfiguredSources replaces the process-wide declarative list of external advisory sources, typically from the config file at CLI startup. Sources are materialized lazily when a default registry is built for a scan, so commands that never query advisories pay no plugin or network cost. Entries from the DEPUTY_ADVISORY_SOURCES environment variable are unioned in at materialization time.

Types

type AggregateResult

type AggregateResult struct {
	Findings   []*vulnerabilityv1.Finding
	Advisories map[string]*vulnerabilityv1.Advisory
	Coverage   *vulnerabilityv1.ScanCoverage
}

AggregateResult is the merged answer across all sources plus a coverage report.

type ConnectOption

type ConnectOption func(*connectOptions)

ConnectOption configures a ConnectRPC source.

func WithConnectClientOptions

func WithConnectClientOptions(opts ...connect.ClientOption) ConnectOption

WithConnectClientOptions appends ConnectRPC client options (interceptors, codecs, auth).

func WithConnectHTTPClient

func WithConnectHTTPClient(c connect.HTTPClient) ConnectOption

WithConnectHTTPClient overrides the HTTP client (e.g. for TLS or auth transports). Defaults to http.DefaultClient.

type PluginOption

type PluginOption func(*pluginOptions)

PluginOption configures a plugin source.

func WithPluginStderr

func WithPluginStderr(w io.Writer) PluginOption

WithPluginStderr routes plugin stderr (useful for debugging plugins).

type Registry

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

Registry aggregates advisory sources: it routes packages to the sources that cover them, merges results with union-with-provenance, and reports coverage.

func NewDefaultRegistry

func NewDefaultRegistry(ctx context.Context, client osv.Client) *Registry

NewDefaultRegistry returns the registry scans use: the built-in OSV source plus any external sources explicitly configured via the config file (SetConfiguredSources) or DEPUTY_ADVISORY_SOURCES. A source that fails to load is skipped with a warning rather than failing the scan; the coverage report shows which sources actually answered.

func NewRegistry

func NewRegistry(sources ...Source) *Registry

NewRegistry builds a registry over the given sources (order is preserved for deterministic provenance ordering).

func (*Registry) Query

func (r *Registry) Query(ctx context.Context, pkgs []*dependencyv1.Package) (*AggregateResult, error)

Query routes pkgs to covering sources, runs them concurrently, and merges. A package no source covers is not an error: it is recorded in Coverage.Uncovered.

type Result

type Result struct {
	Findings   []*vulnerabilityv1.Finding
	Advisories map[string]*vulnerabilityv1.Advisory
}

Result is a single source's answer: findings plus the full advisory records they reference, keyed by advisory ID.

type Source

type Source interface {
	// Info returns the source's identity and declared coverage.
	Info() *pluginv1.AdvisorySourceInfo
	// Query returns the advisories affecting pkgs. Implementations must ignore
	// packages outside their declared Capabilities rather than erroring.
	Query(ctx context.Context, pkgs []*dependencyv1.Package) (*Result, error)
}

Source is an advisory provider: given packages, it returns the advisories (vulnerabilities and malware) affecting them.

The interface is proto-first: a source consumes and produces exactly the proto types that cross the plugin wire, so the built-in OSV source and an external pluginrpc source are interchangeable with no adapter or lossy conversion. Info() is the same proto capability descriptor both advertise.

func LoadPluginSources

func LoadPluginSources(ctx context.Context, programNames []string, opts ...PluginOption) ([]Source, error)

LoadPluginSources starts each named advisory-source plugin and returns the ones that came up, along with a joined error describing any that failed. A plugin that fails to start is skipped, not fatal, so one broken plugin cannot take down discovery of the others.

func NewConnectSource

func NewConnectSource(ctx context.Context, baseURL string, opts ...ConnectOption) (Source, error)

NewConnectSource returns a Source backed by the AdvisorySourceService at baseURL. It calls Info once to cache the service's declared capabilities for routing, so a service that is down at startup fails loudly here rather than silently covering nothing.

func NewOSVSource

func NewOSVSource(client osv.Client) Source

NewOSVSource returns the built-in OSV advisory source. A nil client uses a default OSV client.

func NewPluginSource

func NewPluginSource(ctx context.Context, programName string, opts ...PluginOption) (Source, error)

NewPluginSource starts (lazily, per call) the advisory-source plugin named by programName and returns it as a Source. It calls Info once to cache the plugin's declared capabilities for routing.

type SourceConfig

type SourceConfig struct {
	Program string
	URL     string
}

SourceConfig declares an external advisory source to aggregate with the built-in OSV source. Exactly one of Program or URL must be set: Program names a pluginrpc plugin executable (PATH-resolved name or path), URL is the base URL of a ConnectRPC AdvisorySourceService (a persistent local sidecar or shared remote service).

Jump to

Keyboard shortcuts

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