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
- func DisableSubprocessSources()
- func DiscoverPluginPrograms() ([]string, error)
- func SetConfiguredSources(cfgs []SourceConfig)
- type AggregateResult
- type ConnectOption
- type PluginOption
- type Registry
- type Result
- type Source
- func LoadPluginSources(ctx context.Context, programNames []string, opts ...PluginOption) ([]Source, error)
- func NewConnectSource(ctx context.Context, baseURL string, opts ...ConnectOption) (Source, error)
- func NewOSVSource(client osv.Client) Source
- func NewPluginSource(ctx context.Context, programName string, opts ...PluginOption) (Source, error)
- type SourceConfig
Constants ¶
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.
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.
const PluginProgramPrefix = "deputy-advisory-source-"
PluginProgramPrefix is the executable-name prefix Deputy discovers advisory source plugins by (e.g. "deputy-advisory-source-ghsa").
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
NewOSVSource returns the built-in OSV advisory source. A nil client uses a default OSV client.
func NewPluginSource ¶
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 ¶
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).