remediate

package
v0.5.2 Latest Latest
Warning

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

Go to latest
Published: Sep 2, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Overview

Package remediate turns a vulnerable package into an instruction a developer can act on.

The gap this closes: a scanner says "lodash 4.17.11 is vulnerable, fixed in 4.17.21". But nothing in the project depends on lodash directly -- some build tool three levels up does. Telling somebody to upgrade a package that does not appear in their manifest is how security findings get closed as "won't fix".

What is actually needed is:

vulnerable  lodash@4.17.11
introduced  express@4.17.1 -> body-parser@1.19.0 -> lodash
action      upgrade express to 4.18.2

The direct dependency is the only thing the developer controls, so it is the only thing worth putting in a ticket.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Advice

type Advice struct {
	// Direct reports whether the vulnerable package is itself a direct
	// dependency, in which case there is nothing to trace.
	Direct bool `json:"direct"`
	// Paths are the routes by which the vulnerable package is introduced.
	// More than one means several direct dependencies must move.
	Paths []Path `json:"paths,omitempty"`
	// Action is the single sentence to put in front of a developer.
	Action string `json:"action"`
	// Confident reports whether a graph was actually resolved. Without it the
	// advice falls back to naming the vulnerable package, which is honest but
	// not necessarily actionable.
	Confident bool `json:"confident"`
}

Advice is the remediation verdict for one finding.

type Inventory

type Inventory struct {
	// Direct maps "ecosystem\x00name" to the version resolved for a direct
	// dependency.
	Direct map[string]string
}

Inventory is the package list a scanner observed, used to identify which packages are direct dependencies of this project.

func NewInventory

func NewInventory(findings []finding.Finding, g *scanner.PackageGraph) *Inventory

NewInventory builds an inventory of the project's direct dependencies.

The graph is the better source when a scanner supplied one: findings only cover packages that turned out to be vulnerable, so an inventory built from them alone would miss every direct dependency that happens to be healthy -- which is most of them, and exactly the ones a fix has to move.

type Path

type Path struct {
	// Direct is the dependency named in the project's own manifest.
	Direct string `json:"direct"`
	// DirectVersion is the version currently resolved for it.
	DirectVersion string `json:"direct_version"`
	// Via lists the intermediate packages, nearest-to-direct first.
	Via []string `json:"via,omitempty"`
	// Requirement is the version range the parent asked for, which decides
	// whether a fix is reachable without a major bump.
	Requirement string `json:"requirement,omitempty"`
}

Path is a resolved route from a direct dependency to a vulnerable package.

func LocalPaths

func LocalPaths(g *scanner.PackageGraph, ecosystem, name, version string) []Path

LocalPaths traces routes to a vulnerable package using the dependency graph a scanner already read from the project's lockfiles.

Preferred over the network graph whenever it is available: it is instant, it works offline, and crucially it describes what this project actually resolved rather than what a public registry would resolve today. A lockfile pinned two years ago does not resolve the way deps.dev says it would.

func (Path) String

func (p Path) String() string

String renders the path the way it should appear in a report.

type Resolver

type Resolver struct {
	Client *depsdev.Client
	// Offline skips every network call.
	Offline bool
	// Graph is the dependency graph a scanner already read from this
	// project's lockfiles. When present it is used in preference to the
	// network: it is instant, works offline, and describes what this project
	// actually resolved rather than what a registry would resolve today.
	Graph *scanner.PackageGraph
}

Resolver computes remediation advice from a resolved dependency graph.

func New

func New() *Resolver

func (*Resolver) Apply

func (r *Resolver) Apply(ctx context.Context, findings []finding.Finding, inv *Inventory) map[string]Advice

Apply computes advice for every finding with a package and writes the result back onto Analysis.MinimalUpgrade and Package.IntroducedBy.

Findings whose graph cannot be resolved keep whatever the scanner said. Degrading to the scanner's answer is the right failure mode: a slightly less useful instruction beats an empty one.

Jump to

Keyboard shortcuts

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