Documentation
¶
Index ¶
- Constants
- Variables
- func BuildPayload(file DetectedFile, gitCtx *gitctx.GitContext, repoRoot string) ([]byte, error)
- func ComputeEnrichedSeverities(ev *EnrichedVuln)
- func ExploitMeetsThreshold(ev EnrichedVuln, threshold string) bool
- func HasAnyKev(ev EnrichedVuln) bool
- func IsVersionAffected(installedVersion, versionRange, ecosystem string) bool
- func IsVersionSpecPinned(spec string) bool
- func LookupVulns(ctx context.Context, client *vdb.Client, packages []ScopedPackage, ...) ([]VulnFinding, *LookupStats, error)
- func NormaliseReleaseForEOL(product, version string) string
- func ParseRemediationScores(data map[string]interface{}, ev *EnrichedVuln)
- func PopulateInstalledEdges(groups []ManifestGroup, rootPath string)
- func SSVCToSeverity(decision string) string
- func ScopeIcon(scope string) string
- func ScoreToSeverity(scoreType string, score float64) string
- func SeverityLevel(severity string) int
- func SeverityMeetsThreshold(severity, threshold string) bool
- func SeverityRank(severity string) int
- func SynthesiseFromCDX(cdxDoc map[string]any, packages []ScopedPackage, purls []string) (findings []VulnFinding, enriched []EnrichedVuln, stats *LookupStats)
- func VerifyLocationGone(rootPath string, loc memory.Location, lineSlack int) (bool, string)
- type AffectedSymbols
- type CLIInfo
- type DepGraph
- func (g *DepGraph) DirectCount() int
- func (g *DepGraph) FindPath(targetPkg string) []string
- func (g *DepGraph) IsDirect(pkgName string) bool
- func (g *DepGraph) PopulateGoModGraph(dir string) error
- func (g *DepGraph) PopulateNpmLockEdges(lockFilePath string) error
- func (g *DepGraph) TransitiveCount() int
- type DetectedFile
- type EnrichedVuln
- type ExploitSummary
- type FileType
- type FixesMerged
- type IDSRule
- type LookupStats
- type ManifestGroup
- type ManifestInfo
- type PackageLookupKey
- type PollEngine
- type RemediationInfo
- type RuntimePin
- type ScanError
- type ScanPayload
- type ScanSummary
- type ScanTask
- type ScopedPackage
- type ScoreEntry
- type SemanticMatch
- type UnsupportedFileError
- type UploadEngine
- type VulnFinding
- type VulnSummary
- type WalkOptions
Constants ¶
const ( ScopeProduction = "production" ScopeDevelopment = "development" ScopeTest = "test" ScopePeer = "peer" ScopeOptional = "optional" ScopeProvided = "provided" ScopeRuntime = "runtime" ScopeSystem = "system" )
Scope constants use native package manager terminology.
Variables ¶
var ManifestExtensions = map[string]ManifestInfo{ ".csproj": {Type: "*.csproj", Ecosystem: "nuget", Language: "c#", IsLock: false}, ".tf": {Type: "*.tf", Ecosystem: "terraform", Language: "hcl", IsLock: false}, ".opam": {Type: "*.opam", Ecosystem: "opam", Language: "ocaml", IsLock: false}, ".cabal": {Type: "*.cabal", Ecosystem: "cabal", Language: "haskell", IsLock: false}, ".dockerfile": {Type: "Dockerfile", Ecosystem: "docker", Language: "docker", IsLock: false}, ".containerfile": {Type: "Dockerfile", Ecosystem: "docker", Language: "docker", IsLock: false}, }
ManifestExtensions maps file extensions to manifest metadata. Used for files whose names include a project-specific prefix (e.g. foo.csproj, main.tf).
var ManifestFiles = map[string]ManifestInfo{ "package-lock.json": {Type: "package-lock.json", Ecosystem: "npm", Language: "javascript", IsLock: true}, "package.json": {Type: "package.json", Ecosystem: "npm", Language: "javascript", IsLock: false}, "yarn.lock": {Type: "yarn.lock", Ecosystem: "npm", Language: "javascript", IsLock: true}, "pnpm-lock.yaml": {Type: "pnpm-lock.yaml", Ecosystem: "npm", Language: "javascript", IsLock: true}, "pyproject.toml": {Type: "pyproject.toml", Ecosystem: "pypi", Language: "python", IsLock: false}, "requirements.txt": {Type: "requirements.txt", Ecosystem: "pypi", Language: "python", IsLock: false}, "requirements.in": {Type: "requirements.in", Ecosystem: "pypi", Language: "python", IsLock: false}, "Pipfile": {Type: "Pipfile", Ecosystem: "pypi", Language: "python", IsLock: false}, "Pipfile.lock": {Type: "Pipfile.lock", Ecosystem: "pypi", Language: "python", IsLock: true}, "poetry.lock": {Type: "poetry.lock", Ecosystem: "pypi", Language: "python", IsLock: true}, "uv.lock": {Type: "uv.lock", Ecosystem: "pypi", Language: "python", IsLock: true}, "go.sum": {Type: "go.sum", Ecosystem: "golang", Language: "go", IsLock: true}, "go.mod": {Type: "go.mod", Ecosystem: "golang", Language: "go", IsLock: false}, "Gemfile": {Type: "Gemfile", Ecosystem: "rubygems", Language: "ruby", IsLock: false}, "Gemfile.lock": {Type: "Gemfile.lock", Ecosystem: "rubygems", Language: "ruby", IsLock: true}, "Cargo.toml": {Type: "Cargo.toml", Ecosystem: "cargo", Language: "rust", IsLock: false}, "Cargo.lock": {Type: "Cargo.lock", Ecosystem: "cargo", Language: "rust", IsLock: true}, "pom.xml": {Type: "pom.xml", Ecosystem: "maven", Language: "java", IsLock: false}, "build.gradle": {Type: "build.gradle", Ecosystem: "maven", Language: "java", IsLock: false}, "gradle.lockfile": {Type: "gradle.lockfile", Ecosystem: "maven", Language: "java", IsLock: true}, "build.gradle.kts": {Type: "build.gradle.kts", Ecosystem: "maven", Language: "kotlin", IsLock: false}, "composer.json": {Type: "composer.json", Ecosystem: "composer", Language: "php", IsLock: false}, "composer.lock": {Type: "composer.lock", Ecosystem: "composer", Language: "php", IsLock: true}, "packages.lock.json": {Type: "packages.lock.json", Ecosystem: "nuget", Language: "c#", IsLock: true}, "paket.dependencies": {Type: "paket.dependencies", Ecosystem: "nuget", Language: "c#", IsLock: false}, "paket.lock": {Type: "paket.lock", Ecosystem: "nuget", Language: "c#", IsLock: true}, "Package.swift": {Type: "Package.swift", Ecosystem: "swift", Language: "swift", IsLock: false}, "Package.resolved": {Type: "Package.resolved", Ecosystem: "swift", Language: "swift", IsLock: true}, "pubspec.yaml": {Type: "pubspec.yaml", Ecosystem: "pub", Language: "dart", IsLock: false}, "pubspec.lock": {Type: "pubspec.lock", Ecosystem: "pub", Language: "dart", IsLock: true}, "mix.exs": {Type: "mix.exs", Ecosystem: "hex", Language: "elixir", IsLock: false}, "mix.lock": {Type: "mix.lock", Ecosystem: "hex", Language: "elixir", IsLock: true}, "build.sbt": {Type: "build.sbt", Ecosystem: "maven", Language: "scala", IsLock: false}, "build.lock": {Type: "build.lock", Ecosystem: "maven", Language: "scala", IsLock: true}, "Dockerfile": {Type: "Dockerfile", Ecosystem: "docker", Language: "docker", IsLock: false}, "Containerfile": {Type: "Dockerfile", Ecosystem: "docker", Language: "docker", IsLock: false}, "WORKSPACE": {Type: "WORKSPACE", Ecosystem: "bazel", Language: "starlark", IsLock: false}, "WORKSPACE.bazel": {Type: "WORKSPACE", Ecosystem: "bazel", Language: "starlark", IsLock: false}, "MODULE.bazel": {Type: "MODULE.bazel", Ecosystem: "bazel", Language: "starlark", IsLock: false}, "BUCK": {Type: "BUCK", Ecosystem: "buck", Language: "starlark", IsLock: false}, "BUCK2": {Type: "BUCK2", Ecosystem: "buck", Language: "starlark", IsLock: false}, "conanfile.txt": {Type: "conanfile.txt", Ecosystem: "conan", Language: "c++", IsLock: false}, "conanfile.py": {Type: "conanfile.py", Ecosystem: "conan", Language: "c++", IsLock: false}, "conan.lock": {Type: "conan.lock", Ecosystem: "conan", Language: "c++", IsLock: true}, "vcpkg.json": {Type: "vcpkg.json", Ecosystem: "vcpkg", Language: "c++", IsLock: false}, "Podfile": {Type: "Podfile", Ecosystem: "cocoapods", Language: "swift", IsLock: false}, "Podfile.lock": {Type: "Podfile.lock", Ecosystem: "cocoapods", Language: "swift", IsLock: true}, "Cartfile": {Type: "Cartfile", Ecosystem: "carthage", Language: "swift", IsLock: false}, "Cartfile.resolved": {Type: "Cartfile.resolved", Ecosystem: "carthage", Language: "swift", IsLock: true}, "Project.toml": {Type: "Project.toml", Ecosystem: "julia", Language: "julia", IsLock: false}, "Manifest.toml": {Type: "Manifest.toml", Ecosystem: "julia", Language: "julia", IsLock: true}, "shard.yml": {Type: "shard.yml", Ecosystem: "crystal", Language: "crystal", IsLock: false}, "shard.lock": {Type: "shard.lock", Ecosystem: "crystal", Language: "crystal", IsLock: true}, "deno.json": {Type: "deno.json", Ecosystem: "deno", Language: "typescript", IsLock: false}, "deno.lock": {Type: "deno.lock", Ecosystem: "deno", Language: "typescript", IsLock: true}, "DESCRIPTION": {Type: "DESCRIPTION", Ecosystem: "cran", Language: "r", IsLock: false}, "renv.lock": {Type: "renv.lock", Ecosystem: "cran", Language: "r", IsLock: true}, "rebar.config": {Type: "rebar.config", Ecosystem: "erlang", Language: "erlang", IsLock: false}, "rebar.lock": {Type: "rebar.lock", Ecosystem: "erlang", Language: "erlang", IsLock: true}, "stack.yaml": {Type: "stack.yaml", Ecosystem: "stack", Language: "haskell", IsLock: false}, "cabal.project.freeze": {Type: "cabal.project.freeze", Ecosystem: "cabal", Language: "haskell", IsLock: true}, "opam": {Type: "opam", Ecosystem: "opam", Language: "ocaml", IsLock: false}, "flake.nix": {Type: "flake.nix", Ecosystem: "nix", Language: "nix", IsLock: false}, "flake.lock": {Type: "flake.lock", Ecosystem: "nix", Language: "nix", IsLock: true}, "build.zig.zon": {Type: "build.zig.zon", Ecosystem: "zig", Language: "zig", IsLock: false}, "CPM.cmake": {Type: "CPM.cmake", Ecosystem: "cpm", Language: "cmake", IsLock: false}, "meson.build": {Type: "meson.build", Ecosystem: "meson", Language: "c", IsLock: false}, }
ManifestFiles maps known manifest filenames (exact basename) to their metadata.
var SupportedManifestTypes = map[string]bool{ "package.json": true, "package-lock.json": true, "yarn.lock": true, "pnpm-lock.yaml": true, "pyproject.toml": true, "requirements.txt": true, "requirements.in": true, "Pipfile": true, "Pipfile.lock": true, "poetry.lock": true, "uv.lock": true, "go.sum": true, "go.mod": true, "Gemfile": true, "Gemfile.lock": true, "Cargo.toml": true, "Cargo.lock": true, "pom.xml": true, "build.gradle": true, "gradle.lockfile": true, "build.gradle.kts": true, "composer.json": true, "composer.lock": true, "packages.lock.json": true, "paket.dependencies": true, "paket.lock": true, "*.csproj": true, "Package.swift": true, "Package.resolved": true, "pubspec.yaml": true, "pubspec.lock": true, "mix.exs": true, "mix.lock": true, "build.sbt": true, "build.lock": true, "Dockerfile": true, "*.tf": true, "github-actions.yml": true, "conanfile.txt": true, "conan.lock": true, "vcpkg.json": true, "Podfile": true, "Podfile.lock": true, "Cartfile": true, "Cartfile.resolved": true, "Project.toml": true, "Manifest.toml": true, "shard.yml": true, "shard.lock": true, "deno.json": true, "deno.lock": true, "DESCRIPTION": true, "renv.lock": true, "rebar.config": true, "rebar.lock": true, "stack.yaml": true, "*.cabal": true, "cabal.project.freeze": true, "*.opam": true, "opam": true, "flake.nix": true, "flake.lock": true, "build.zig.zon": true, "meson.build": true, "WORKSPACE": true, "MODULE.bazel": true, "BUCK": true, "BUCK2": true, "CPM.cmake": true, "CMakeLists.txt": true, }
SupportedManifestTypes lists manifest types that have a local parser implemented. Files detected but absent from this map are shown as "[not supported]" in scan output.
var ValidExploitThresholds = []string{"poc", "active", "weaponized"}
ValidExploitThresholds lists the accepted values for the --exploits flag, in ascending order of exploit maturity (least → most dangerous).
var ValidSeverityThresholds = []string{"low", "medium", "high", "critical"}
ValidSeverityThresholds lists the accepted --severity flag values in ascending order.
Functions ¶
func BuildPayload ¶
func BuildPayload(file DetectedFile, gitCtx *gitctx.GitContext, repoRoot string) ([]byte, error)
BuildPayload constructs a ScanPayload for a manifest file and marshals it to JSON. gitCtx may be nil (non-git directory). repoRoot may be empty.
func ComputeEnrichedSeverities ¶
func ComputeEnrichedSeverities(ev *EnrichedVuln)
ComputeEnrichedSeverities fills the per-source severity fields and MaxSeverity on ev after all score data has been populated.
func ExploitMeetsThreshold ¶
func ExploitMeetsThreshold(ev EnrichedVuln, threshold string) bool
ExploitMeetsThreshold reports whether ev's exploit signals reach the given tier.
Tiers form a strict hierarchy — each tier also captures all higher-maturity signals:
poc : any public exploit exists (ExploitCount > 0, or any KEV entry) active : known active exploitation (InCisaKev || InVulnCheckKev || InEuKev || HasWeaponized) weaponized: weaponised in-the-wild (ExploitIntel.HasWeaponized)
func HasAnyKev ¶
func HasAnyKev(ev EnrichedVuln) bool
HasAnyKev returns true if the vulnerability is listed in any KEV catalog (CISA, VulnCheck, or EU ENISA).
func IsVersionAffected ¶
IsVersionAffected checks whether installedVersion falls within the affected version range string returned by the VDB API.
Supported range formats:
">= 2.0.0, < 2.3.1" comma-separated constraints "[2.0.0, 2.3.1)" interval notation "< 3.0.0" single constraint "2.3.1" exact version match
Returns true if the installed version IS affected. When parsing fails the function returns true (assume affected) to err on the side of caution.
func IsVersionSpecPinned ¶
IsVersionSpecPinned reports whether spec represents an exact version pin. An empty spec (e.g. lock-file entries) is treated as pinned. Specs that begin with range operators (^, ~, >=, >, <=, <, !=) or are symbolic (*, latest, x) are considered unpinned.
func LookupVulns ¶
func LookupVulns( ctx context.Context, client *vdb.Client, packages []ScopedPackage, concurrency int, progress func(done, total int), ) ([]VulnFinding, *LookupStats, error)
LookupVulns queries the VDB API for vulnerabilities affecting the given packages. It deduplicates by (name, ecosystem) and runs lookups with bounded concurrency. The progress callback is called with (done, total) after each package is processed.
Packages with names shorter than 3 characters are skipped (VDB search minimum).
On partial failure (e.g. rate limit hit midway), any results collected before the error are returned alongside the error so the caller can decide whether to use them. Stats always reflect the full picture.
func NormaliseReleaseForEOL ¶
NormaliseReleaseForEOL reduces a full version string to the form expected by the VDB EOL API for the given product.
go : major.minor ("1.21.3" → "1.21", "1.21" → "1.21")
nodejs : major only ("18.20.4" → "18", "18" → "18")
python : major.minor ("3.10.4" → "3.10", "3.10" → "3.10")
ruby : major.minor ("3.2.1" → "3.2", "3.2" → "3.2")
Returns "" if the version string cannot be parsed.
func ParseRemediationScores ¶
func ParseRemediationScores(data map[string]interface{}, ev *EnrichedVuln)
ParseRemediationScores extracts scores from the remediation plan response into the EnrichedVuln. These are displayed but not used for primary sorting.
func PopulateInstalledEdges ¶
func PopulateInstalledEdges(groups []ManifestGroup, rootPath string)
PopulateInstalledEdges attempts to build dependency graph edges for each manifest group by reading locally installed package manifests. This enriches both SBOM dependency trees and --paths output. Errors are silently skipped.
func SSVCToSeverity ¶
SSVCToSeverity maps an SSVC decision string to an approximate severity label. SSVC decisions are: Act, Attend, Track*, Track, Defer.
func ScoreToSeverity ¶
ScoreToSeverity converts a numeric score of a given type to a severity label. Supported types: epss, coalition_ess (cess), cvss* variants. Returns "unscored" when the type is unrecognised or the score is zero.
func SeverityLevel ¶
SeverityLevel returns a numeric level for severity (higher = more severe). This is the inverse of SeverityRank and is used for threshold comparisons.
unscored → 0 low → 1 medium → 2 high → 3 critical → 4
func SeverityMeetsThreshold ¶
SeverityMeetsThreshold reports whether the given severity meets or exceeds the threshold severity. "unscored" never triggers the threshold. Examples:
SeverityMeetsThreshold("critical", "high") → true
SeverityMeetsThreshold("medium", "high") → false
SeverityMeetsThreshold("high", "high") → true
SeverityMeetsThreshold("unscored", "low") → false
func SeverityRank ¶
SeverityRank returns a numeric rank for severity (lower = more severe). Kept for backward-compatibility; prefer SeverityLevel for threshold logic.
func SynthesiseFromCDX ¶ added in v3.6.0
func SynthesiseFromCDX(cdxDoc map[string]any, packages []ScopedPackage, purls []string) (findings []VulnFinding, enriched []EnrichedVuln, stats *LookupStats)
SynthesiseFromCDX converts an upstream CycloneDX 1.6 document into the internal finding shapes. Returns nil slices when the document is empty or malformed — callers should treat a nil result as "fall back to legacy".
packages and purls are parallel arrays — `purls[i]` is the PURL the caller computed (via cdx.BuildLocalPurl) for `packages[i]`. Empty purl entries are silently ignored. Keeping the purl derivation outside this package avoids a scan→cdx import cycle.
func VerifyLocationGone ¶ added in v3.2.0
VerifyLocationGone returns true when the finding evidence at loc is no longer present on disk. "Gone" means: the file is missing, OR the original snippet is not found within a ±lineSlack window around loc.StartLine.
rootPath is prepended when loc.File is relative. When loc.Snippet is empty (older records without snippet capture) the verifier returns gone=false so the caller leaves the record untouched — we never auto-resolve on a guess.
Types ¶
type AffectedSymbols ¶ added in v3.6.0
AffectedSymbols carries the lower-efficacy symbol-level fallback shipped on every cli.sca response (all tiers). The CLI greps local source for these literal names to emit a "grep-match" reachability signal when the higher-efficacy tree-sitter path has no queries for the CVE.
func (*AffectedSymbols) HasAny ¶ added in v3.6.0
func (a *AffectedSymbols) HasAny() bool
HasAny returns true if any list is populated.
type DepGraph ¶
type DepGraph struct {
DirectDeps map[string]ScopedPackage // name → direct dependency
AllDeps map[string]ScopedPackage // name → any dependency (direct or transitive)
Edges map[string][]string // parent module name → child module names (from go mod graph, etc.)
}
DepGraph tracks direct vs transitive dependency relationships for a manifest group. A manifest group is a set of related files in the same directory (e.g., go.mod + go.sum).
func BuildGenericDepGraph ¶
func BuildGenericDepGraph(directPkgs, lockPkgs []ScopedPackage) *DepGraph
BuildGenericDepGraph is a generic build graph correlator for ecosystems that have a simple direct manifest + lock file relationship (e.g., Cargo.toml/Cargo.lock).
func BuildGoDepGraph ¶
func BuildGoDepGraph(goModPkgs, goSumPkgs []ScopedPackage) *DepGraph
BuildGoDepGraph correlates go.mod (direct) and go.sum (all) packages from the same directory to determine which dependencies are direct vs transitive.
func BuildNpmDepGraph ¶
func BuildNpmDepGraph(pkgJsonPkgs, lockPkgs []ScopedPackage) *DepGraph
BuildNpmDepGraph correlates package.json (direct) and package-lock.json (all) packages from the same directory.
func BuildPypiDepGraph ¶
func BuildPypiDepGraph(directPkgs, lockPkgs []ScopedPackage) *DepGraph
BuildPypiDepGraph correlates pyproject.toml (direct) and lock files (uv.lock, poetry.lock, Pipfile.lock) to classify direct vs transitive dependencies. Package name comparison is case-folded and normalises dashes/underscores to handle the common PyPI naming quirks.
func (*DepGraph) DirectCount ¶
DirectCount returns the number of direct dependencies.
func (*DepGraph) FindPath ¶
FindPath returns the shortest dependency chain from any direct dep to targetPkg. Returns nil if no path exists or edge data is unavailable. The returned slice is the chain: [direct-dep, intermediate, ..., targetPkg].
func (*DepGraph) IsDirect ¶
IsDirect returns true if the package was declared directly in the manifest. For PyPI packages, name lookup is also attempted with dash/underscore/case normalisation so that e.g. "PyYAML" matches a key stored as "pyyaml".
func (*DepGraph) PopulateGoModGraph ¶
PopulateGoModGraph runs "go mod graph" in the given directory and populates the Edges map with the dependency relationships. Strips version suffixes so edges use bare module names matching package names.
func (*DepGraph) PopulateNpmLockEdges ¶
PopulateNpmLockEdges parses package-lock.json (v2/v3) and populates the Edges map from the nested node_modules path structure. In v3 format, the key "node_modules/foo/node_modules/bar" means foo depends on bar.
func (*DepGraph) TransitiveCount ¶
TransitiveCount returns the number of transitive (non-direct) dependencies.
type DetectedFile ¶
type DetectedFile struct {
Path string
RelPath string // relative to scan root
FileType FileType
ManifestInfo *ManifestInfo // non-nil for manifest files
SBOMVersion string // e.g. "SPDX-2.3", "1.5" for CycloneDX
Supported bool // whether the backend accepts this file type
}
DetectedFile represents a detected scannable file
func WalkForScanFiles ¶
func WalkForScanFiles(opts WalkOptions) ([]DetectedFile, error)
WalkForScanFiles walks the filesystem from root, up to maxDepth, looking for manifest files and potential SBOM documents.
type EnrichedVuln ¶
type EnrichedVuln struct {
VulnFinding
Confirmed bool // true if installed version is in affected range
IsMalicious bool // malware/malicious package — highest sort priority
AffectedRange string // e.g., ">= 2.0.0, < 2.3.1"
PathCount int // number of source files / transitive paths introducing this vuln
ThreatExposure float64 // x_threatExposure from VDB — primary sort key
EPSSScore float64 // displayed
EPSSPercentile float64 // displayed
CVSSScore float64 // displayed
CoalitionESS float64 // displayed
ExploitIntel *ExploitSummary
Remediation *RemediationInfo
SSVCDecision string // "Act", "Attend", "Track*", "Track"
FixAvailability string // "available", "partial", "no_fix"
IDSRules []IDSRule
// Per-source severity ratings (coerced from numeric scores / decisions).
EPSSSeverity string // severity derived from EPSS probability
CESSeverity string // severity derived from Coalition ESS score
CVSSSeverity string // severity derived from CVSS score
SSVCSeverity string // severity derived from SSVC decision
// MaxSeverity is the highest severity across all scoring sources for this vuln.
// It is used for --severity threshold evaluation.
MaxSeverity string
// MatchMethod records how this vuln was matched to the package (e.g. "name+version", "cpe", "name-only").
MatchMethod string
// Reachability records the outcome of the local code-analysis pass
// for this vuln. Values:
// "direct" — vulnerable AST node lives inside the installed
// package's own source (highest confidence).
// "transitive" — vulnerable AST node lives in first-party code
// that calls into the affected dep.
// "semantic" — the lower-efficacy fallback: the affected
// routine / file / module name appears literally
// in your source (e.g. an import statement or
// typed usage). Indicates intent to use the
// affected element but not a proven call path.
// "unreachable" — queries ran and nothing matched.
// empty — no analysis was performed (no data to compare).
Reachability string
// AffectedSymbols is the symbol-level fallback returned by the API for
// every tier. Populated whether or not tree-sitter queries existed.
AffectedSymbols *AffectedSymbols
// SemanticMatches lists per-CVE source hits from the semantic
// reachability pass — one entry per (file, line, symbol). Empty when
// Reachability != "semantic".
SemanticMatches []SemanticMatch
}
EnrichedVuln extends VulnFinding with version-filtered, enriched data.
func EnrichVulns ¶
func EnrichVulns( ctx context.Context, v1Client *vdb.Client, v2Client *vdb.Client, findings []VulnFinding, packages []ScopedPackage, concurrency int, progress func(done, total int), ) ([]EnrichedVuln, error)
EnrichVulns filters vulnerabilities by affected version range (via V2Affected), fetches exploit intelligence and remediation plans, and deduplicates by (CveID, PkgName).
type ExploitSummary ¶
type ExploitSummary struct {
ExploitCount int
Sources []string
HasWeaponized bool
HighestMaturity string
}
ExploitSummary captures exploit intelligence for a vulnerability.
type FixesMerged ¶
type FixesMerged struct {
Registry map[string]interface{}
Distributions map[string]interface{}
Source map[string]interface{}
}
FixesMerged holds merged fix data from three V2 endpoints.
type IDSRule ¶
type IDSRule struct {
Type string // "snort" or "suricata"
Content string
Source string
CveID string
}
IDSRule represents a snort or suricata detection rule.
func CollectIDSRules ¶
func CollectIDSRules(vulns []EnrichedVuln) []IDSRule
CollectIDSRules gathers all IDS rules from enriched vulns.
type LookupStats ¶
type LookupStats struct {
Total int // unique packages queried (after dedup)
Succeeded int // API calls that returned successfully
Failed int // API calls that returned an error
Skipped int // packages skipped (name too short)
Cancelled int // packages not attempted (cancelled after fatal error)
}
LookupStats summarises the outcome of a LookupVulns call.
type ManifestGroup ¶
type ManifestGroup struct {
Dir string // relative directory
Ecosystem string // e.g., "golang", "npm"
Files []string // relative paths of constituent manifest files
Graph *DepGraph // direct vs transitive classification
Packages []ScopedPackage // all packages from this group
}
ManifestGroup holds related manifest files from the same directory/ecosystem.
func BuildManifestGroups ¶
func BuildManifestGroups(filePackages map[string][]ScopedPackage, fileEcosystems map[string]string) []ManifestGroup
BuildManifestGroups correlates manifest results by directory and ecosystem, building dependency graphs where possible.
type ManifestInfo ¶
type ManifestInfo struct {
Type string // canonical filename used as the manifest "type" parameter
Ecosystem string
Language string
IsLock bool
}
ManifestInfo describes a known manifest file
func DetectManifest ¶
func DetectManifest(filename string) (*ManifestInfo, bool)
DetectManifest checks if a file is a known manifest. It checks in order: exact basename → file extension → path pattern (GitHub Actions).
type PackageLookupKey ¶
PackageLookupKey uniquely identifies a package by name and ecosystem.
type PollEngine ¶
type PollEngine struct {
Client *vdb.Client
Interval time.Duration // polling interval (default 5s)
OnProgress func(*ScanTask) // callback for UI updates (called from goroutines)
}
PollEngine handles concurrent polling for scan results.
type RemediationInfo ¶
RemediationInfo captures remediation plan details.
type RuntimePin ¶
type RuntimePin struct {
Product string // VDB EOL product name: "go", "nodejs", "python", "ruby"
Release string // normalised for the EOL API: "1.21", "18", "3.10"
RawVersion string // raw version string from the file
SourceFile string // relative path of the pin file within the project root
}
RuntimePin records a runtime version detected from a version-pin file.
func DetectRuntimeVersionPins ¶
func DetectRuntimeVersionPins(rootPath string) []RuntimePin
DetectRuntimeVersionPins scans rootPath for common runtime version-pin files and returns the detected runtime versions. Only the project root is inspected (no recursion). Errors reading individual files are silently skipped.
Files inspected: go.mod, .nvmrc, .node-version, .python-version, .tool-versions, .ruby-version, Gemfile, Dockerfile, Containerfile. LTS aliases in .nvmrc (e.g. "lts/hydrogen") are silently skipped.
type ScanError ¶
type ScanError struct {
Message string
}
ScanError represents a scan-side error returned by the API.
type ScanPayload ¶
type ScanPayload struct {
Version string `json:"version"`
CLI CLIInfo `json:"cli"`
Git *gitctx.GitContext `json:"git,omitempty"`
FileTree *filetree.FileTreeContext `json:"fileTree,omitempty"`
ManifestType string `json:"manifestType"`
Ecosystem string `json:"ecosystem"`
Timestamp int64 `json:"timestamp"`
}
ScanPayload is the JSON metadata sent alongside manifest files.
type ScanSummary ¶
type ScanSummary struct {
TotalFiles int
TotalVulns int
MalwareCount int
CriticalCount int
HighCount int
MediumCount int
LowCount int
ErrorCount int
}
ScanSummary aggregates results across all tasks.
func Summarize ¶
func Summarize(tasks []*ScanTask) ScanSummary
Summarize computes a summary from completed scan tasks.
func (ScanSummary) FormatSummary ¶
func (s ScanSummary) FormatSummary() string
FormatSummary returns a human-readable summary string.
type ScanTask ¶
type ScanTask struct {
File DetectedFile
ScanID string
Status string // "queued","uploading","uploaded","polling","complete","error"
UploadStart time.Time
UploadEnd time.Time
PollStart time.Time
PollEnd time.Time
Error error
RawResult map[string]interface{}
Vulns []VulnSummary
}
ScanTask tracks one file's lifecycle through upload -> poll -> results.
func (*ScanTask) PollDuration ¶
PollDuration returns the time spent polling.
func (*ScanTask) TotalDuration ¶
TotalDuration returns the total time from upload start to poll completion.
func (*ScanTask) UploadDuration ¶
UploadDuration returns the time spent uploading.
type ScopedPackage ¶
type ScopedPackage struct {
Name string
Version string
VersionSpec string // raw version spec from manifest before cleaning (e.g. "^1.0.0", ">=2.3"); empty for lock-file entries
Ecosystem string
Scope string // native scope label (production, development, test, peer, etc.)
SourceFile string // relative path of the manifest file that declared this package
IsDirect bool // true if declared in the manifest (e.g., go.mod), false if transitive (e.g., go.sum)
GitHubURL string // optional: "owner/repo" for packages whose VCS is known from the manifest
}
ScopedPackage represents a parsed dependency with scope information.
func ParseManifestWithScope ¶
func ParseManifestWithScope(filePath, manifestType string) ([]ScopedPackage, error)
ParseManifestWithScope parses a manifest file and returns packages with scope information. It uses the file's manifest type to choose the appropriate parser.
type ScoreEntry ¶
type ScoreEntry struct {
Type string // "epss","coalition_ess","cvssv4","cvssv3.1","cvssv3.0","cvssv2"
Score float64
Source string
}
ScoreEntry represents a single vulnerability score.
type SemanticMatch ¶ added in v3.6.0
type SemanticMatch struct {
File string
Line int
Symbol string
Kind string // "routine" | "file" | "module"
}
SemanticMatch is one source hit produced by the semantic reachability fallback. The CLI's pretty-printer renders these under a Semantic Reachability section so users can jump straight to file:line.
type UnsupportedFileError ¶
type UnsupportedFileError struct {
Path string
}
UnsupportedFileError is returned when a file type is not supported for upload.
func (*UnsupportedFileError) Error ¶
func (e *UnsupportedFileError) Error() string
type UploadEngine ¶
type UploadEngine struct {
Client *vdb.Client
Concurrency int // max concurrent uploads (default 5)
OnProgress func(*ScanTask) // callback for UI updates (called from goroutines)
GitContext *gitctx.GitContext // shared git context (collected once, may be nil)
RepoRoot string // git repo root path (may be empty)
}
UploadEngine handles concurrent file uploads to the VDB API.
func (*UploadEngine) UploadAll ¶
func (e *UploadEngine) UploadAll(ctx context.Context, files []DetectedFile) []*ScanTask
UploadAll uploads all detected files concurrently using a bounded semaphore. Returns a ScanTask for each file with status "uploaded" or "error".
type VulnFinding ¶
type VulnFinding struct {
CveID string
PackageName string
PackageVer string
Ecosystem string
Scope string
Severity string
Score float64
MetricType string
VectorString string
SourceFile string
Source string // upstream vulnerability source name (empty = vulnetix)
InCisaKev bool
InVulnCheckKev bool
InEuKev bool
ExploitCount int
}
VulnFinding represents a vulnerability found during a local scan.
type VulnSummary ¶
type VulnSummary struct {
VulnID string
IsMalicious bool
Scores []ScoreEntry // ordered: EPSS > Coalition ESS > CVSSv4 > CVSS3 > CVSS2
Severity string
PackageName string
PackageVer string
SourceFile string // which scanned file this came from
// Lazy-loaded detail fields (nil until fetched)
Exploits *map[string]interface{}
Timeline *map[string]interface{}
Fixes *FixesMerged
Remediation *map[string]interface{}
Advisories *map[string]interface{}
Workarounds *map[string]interface{}
Kev *map[string]interface{}
}
VulnSummary is a parsed vulnerability from scan results.
func AllVulns ¶
func AllVulns(tasks []*ScanTask) []VulnSummary
AllVulns returns all vulnerabilities across all tasks, sorted by severity.
func ParseVulnsFromScanResult ¶
func ParseVulnsFromScanResult(raw map[string]interface{}, sourceFile string) []VulnSummary
ParseVulnsFromScanResult extracts vulnerability summaries from a scan status API response.
func (*VulnSummary) TopScore ¶
func (v *VulnSummary) TopScore() (string, float64)
TopScore returns the highest-priority score, or 0 if none.
type WalkOptions ¶
type WalkOptions struct {
RootPath string
MaxDepth int
Excludes []string // glob patterns to exclude
}
WalkOptions configures the filesystem walk behavior.