deps

package
v1.2.1 Latest Latest
Warning

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

Go to latest
Published: Jun 7, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Overview

Package deps implements bumper's dependency guardrail: it parses lockfiles entirely locally and talks to the hosted Advisor (advisor.bumper.sh) over REST. Only package coordinates ({ecosystem, name, version}) ever leave the machine — never source. The parsers here mirror the browser parsers shipped in bumper-web/lib/lockfiles.ts so the CLI and the free web tool agree.

Index

Constants

View Source
const DefaultAdvisorURL = "https://advisor.bumper.sh"

DefaultAdvisorURL is the hosted, public, read-only Advisor. Override with --advisor-url or $BUMPER_ADVISOR_URL to point at a self-hosted instance.

Variables

View Source
var ErrRateLimited = errors.New("rate limited by the Advisor (HTTP 429)")

ErrRateLimited is returned when the Advisor replies 429 (the /scan limiter).

View Source
var Formats = []Format{
	{"npm", "npm · package-lock.json", "npm", []string{"package-lock.json", "npm-shrinkwrap.json"}},
	{"pip", "Python · requirements.txt", "PyPI", []string{"requirements.txt"}},
	{"poetry", "Python · poetry.lock", "PyPI", []string{"poetry.lock"}},
	{"uv", "Python · uv.lock", "PyPI", []string{"uv.lock"}},
	{"pipfile", "Python · Pipfile.lock", "PyPI", []string{"pipfile.lock"}},
	{"gosum", "Go · go.sum", "Go", []string{"go.sum"}},
	{"gomod", "Go · go.mod", "Go", []string{"go.mod"}},
	{"cargo", "Rust · Cargo.lock", "crates.io", []string{"cargo.lock"}},
	{"gemfile", "Ruby · Gemfile.lock", "RubyGems", []string{"gemfile.lock"}},
}

Formats is the v1 set: npm + Python + Go + Rust + Ruby (parity with the web tool).

View Source
var LockfileCandidates = []string{
	"package-lock.json", "npm-shrinkwrap.json",
	"requirements.txt", "poetry.lock", "uv.lock", "Pipfile.lock",
	"go.sum", "go.mod", "Cargo.lock", "Gemfile.lock",
}

LockfileCandidates are the real on-disk filenames probed when auto-detecting a directory (preserves the real casing — Linux is case-sensitive).

Functions

func DetectFormat

func DetectFormat(filename, content string) string

DetectFormat resolves a format id from the filename, falling back to content sniffing for renamed/pasted files. Returns "" if unrecognized.

func Guard

func Guard(r io.Reader, w io.Writer, client *Client, shellTool string) (reason string, err error)

Guard is the PreToolUse pre-install hook: it blocks an install of a known-MALICIOUS package, with an informative reason so the agent self-corrects. Fail-open throughout — a bumper or network error must never wedge the shell. shellTool is the host agent's shell-execution tool name (e.g. "Bash" for Claude Code, "launch-process" for Augment); the hook is a no-op for any other tool.

It writes the JSON deny decision to w and returns the deny reason ("" = allow), so the caller can ALSO surface the block via stderr + exit 2 — the universal backstop honored by every agent (and required by Gemini, which ignores the JSON).

func ResolveAdvisorURL

func ResolveAdvisorURL(flagVal string) string

ResolveAdvisorURL applies precedence: explicit flag > $BUMPER_ADVISOR_URL > default.

func Watch

func Watch(r io.Reader, w io.Writer, client *Client, fallbackDir, shellTool, postEvent string) error

Watch is the post-install hook (model B): after an install, it runs the scan itself, stays silent when clean, and on findings injects context that nudges the agent to triage (spawning a subagent if it supports one). Non-blocking, fail-open. shellTool is the host agent's shell-execution tool name (see Guard); postEvent is the agent's post-tool event name echoed as hookEventName ("PostToolUse" for Claude/Augment, "AfterTool" for Gemini) — the additionalContext field itself is shared.

Types

type Client

type Client struct {
	BaseURL string
	HTTP    *http.Client
}

Client is a thin Advisor REST client.

func NewClient

func NewClient(baseURL string) *Client

NewClient builds a client for an already-resolved base URL.

func (*Client) MalwareCheck

func (c *Client) MalwareCheck(deps []Dep) (*MalwareResult, error)

MalwareCheck runs a name-level known-malicious check on the named packages.

func (*Client) Scan

func (c *Client) Scan(deps []Dep, includeMalware bool) (*ScanResult, error)

Scan runs a version-aware vulnerability scan (+ malware) over deps, chunked so big lockfiles fully cover under the API's per-request cap.

type Dep

type Dep struct {
	Ecosystem string `json:"ecosystem"`
	Package   string `json:"package"`
	Version   string `json:"version"`
}

Dep is a single resolved dependency coordinate — the only thing sent to the Advisor.

func CollectLockfileDeps

func CollectLockfileDeps(dir string) []Dep

CollectLockfileDeps parses every known lockfile present in dir and returns the merged, deduped coordinates. Used by `bumper deps` (no path) and `deps watch`.

type Format

type Format struct {
	ID        string
	Label     string
	Ecosystem string
	Filenames []string // lowercase, for case-insensitive matching
}

Format describes a supported lockfile.

type MalwareAdvisory

type MalwareAdvisory struct {
	ID      string `json:"id"`
	Summary string `json:"summary"`
	Details string `json:"details"`
	Refs    []Ref  `json:"refs"`
}

type MalwareHit

type MalwareHit struct {
	Ecosystem  string            `json:"ecosystem"`
	Package    string            `json:"package"`
	Malicious  bool              `json:"malicious"`
	Advisories []MalwareAdvisory `json:"advisories"`
}

type MalwareResult

type MalwareResult struct {
	Status         string       `json:"status"`
	Checked        int          `json:"checked"`
	MaliciousCount int          `json:"malicious_count"`
	Skipped        int          `json:"skipped"`
	Results        []MalwareHit `json:"results"`
}

type ParseResult

type ParseResult struct {
	Format    string
	Label     string
	Ecosystem string
	Deps      []Dep
}

ParseResult is a parsed lockfile.

func ParseLockfile

func ParseLockfile(filename, content string) (*ParseResult, error)

ParseLockfile detects + parses a lockfile's content into deduped coordinates.

type Ref

type Ref struct {
	URL  string `json:"url"`
	Type string `json:"type"`
}

type ScanFinding

type ScanFinding struct {
	Ecosystem string        `json:"ecosystem"`
	Package   string        `json:"package"`
	Version   string        `json:"version"`
	Vulns     []ScanVuln    `json:"vulns"`
	Malware   []ScanMalware `json:"malware"`
}

type ScanMalware

type ScanMalware struct {
	ID      string `json:"id"`
	Summary string `json:"summary"`
}

type ScanResult

type ScanResult struct {
	Status          string        `json:"status"`
	Scanned         int           `json:"scanned"`
	VulnerableCount int           `json:"vulnerable_count"`
	MalwareCount    int           `json:"malware_count"`
	Skipped         int           `json:"skipped"`
	Truncated       bool          `json:"truncated"`
	Findings        []ScanFinding `json:"findings"`
}

type ScanVuln

type ScanVuln struct {
	ID           string `json:"id"`
	Severity     string `json:"severity"`
	FixedVersion string `json:"fixed_version"`
	HasAIInsight bool   `json:"has_ai_insight"`
}

Jump to

Keyboard shortcuts

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