Documentation
¶
Overview ¶
Package memory manages the .vulnetix/memory.yaml file that persists scan state between runs — last scan summary, history, and cached findings.
Index ¶
- Constants
- Variables
- func Save(vulnetixDir string, m *Memory) error
- type CWSSData
- type Decision
- type DiscoveryInfo
- type EnrichedFinding
- type EnvironmentContext
- type ExploitInfo
- type FindingRecord
- type HistoryEntry
- type Location
- type Memory
- func (m *Memory) GetFinding(cveID string) *FindingRecord
- func (m *Memory) GetOpenFindings() map[string]FindingRecord
- func (m *Memory) GetOpenFindingsByTools(tools []string) map[string]FindingRecord
- func (m *Memory) GetOpenSASTFindingsByTools(tools []string) map[string]SASTFindingRecord
- func (m *Memory) MarkSASTFindingResolved(fingerprint string)
- func (m *Memory) ReconcileFindings(currentCVEs map[string]bool) []StateChange
- func (m *Memory) ReconcileTool(ctx ReconcileContext) []StateChange
- func (m *Memory) RecordCategorizedFindings(tool string, findings map[string]FindingRecord)
- func (m *Memory) RecordEnrichedFindings(findings []EnrichedFinding)
- func (m *Memory) RecordReachability(vulnID string, evidence *ReachabilityEvidence)
- func (m *Memory) RecordSASTFindings(findings []SASTFindingRecord)
- func (m *Memory) RecordScan(rec ScanRecord)
- func (m *Memory) RecordVDBQuery(q VDBQuery)
- func (m *Memory) RecordVulnLookup(vulnID string, data interface{})
- func (m *Memory) SetFinding(cveID string, data FindingRecord)
- func (m *Memory) SetScanContext(ctx *ScanContext)
- func (m *Memory) UpdateEnvironment(env *EnvironmentContext)
- type ReachabilityEvidence
- type ReachabilityMatch
- type ReconcileContext
- type RemediationData
- type SASTFindingRecord
- type ScanContext
- type ScanRecord
- type ScopeStats
- type ScoreData
- type StateChange
- type ThreatModel
- type VDBQuery
- type VersionInfo
Constants ¶
const ( ToolSCA = "sca" ToolSAST = "sast" ToolIaC = "iac" ToolSecrets = "secrets" ToolContainer = "container" ToolQuality = "quality" ToolLicense = "license" )
Tool identifies which scan family produced a finding. Persisted on every FindingRecord / SASTFindingRecord so triage can filter by category.
const (
// FileName is the basename of the memory file inside .vulnetix/.
FileName = "memory.yaml"
)
Variables ¶
var AllTools = []string{ ToolSCA, ToolSAST, ToolIaC, ToolSecrets, ToolContainer, ToolQuality, ToolLicense, }
AllTools is the canonical list of tool tags persisted in memory.
Functions ¶
Types ¶
type CWSSData ¶
type CWSSData struct {
Score float64 `yaml:"score"`
Priority string `yaml:"priority,omitempty"`
Factors map[string]float64 `yaml:"factors,omitempty"`
}
CWSSData holds a CWSS-derived priority score.
type Decision ¶
type Decision struct {
Choice string `yaml:"choice"`
Reason string `yaml:"reason"`
Date string `yaml:"date"` // RFC3339
Actor string `yaml:"actor,omitempty"`
}
Decision records a user's decision about a vulnerability.
type DiscoveryInfo ¶
type DiscoveryInfo struct {
Date string `yaml:"date"`
Source string `yaml:"source"` // scan | hook | user | vulnetix-triage | github-triage
File string `yaml:"file,omitempty"`
SBOM string `yaml:"sbom,omitempty"`
}
DiscoveryInfo records how and when a vulnerability was discovered.
type EnrichedFinding ¶
type EnrichedFinding struct {
CveID string
PackageName string
InstalledVersion string
Ecosystem string
MaxSeverity string
AffectedRange string
IsMalicious bool
Confirmed bool
InCisaKev bool
InEuKev bool
PathCount int
SourceFiles []string
IntroducedPaths [][]string
// Scores
CVSSScore float64
CVSSSeverity string
EPSSScore float64
EPSSPercentile float64
EPSSSeverity string
CoalitionESS float64
CESSeverity string
SSVCDecision string
SSVCSeverity string
ThreatExposure float64
// Fix
FixVersion string
ExploitInfo *ExploitInfo
Remediation *RemediationData
}
EnrichedFinding is the input struct for RecordEnrichedFindings. It is a flat representation of data extracted from scan enrichment.
type EnvironmentContext ¶
type EnvironmentContext struct {
Platform string `yaml:"platform,omitempty"`
GitLocalDir string `yaml:"git_local_dir,omitempty"`
GitBranch string `yaml:"git_branch,omitempty"`
GitCommit string `yaml:"git_commit,omitempty"`
GitRemoteURL string `yaml:"remote_url,omitempty"`
GitRemoteBranch string `yaml:"remote_branch,omitempty"`
CommitterName string `yaml:"committer_name,omitempty"`
CommitterEmail string `yaml:"committer_email,omitempty"`
GithubOrg string `yaml:"github_org,omitempty"`
GithubRepo string `yaml:"github_repo,omitempty"`
GithubPR string `yaml:"github_pr,omitempty"`
PackageManager string `yaml:"package_manager,omitempty"`
ManifestFormat string `yaml:"manifest_format,omitempty"`
}
EnvironmentContext captures the auto-gathered or flag-provided context for a VDB query session. This schema is shared with the Claude Code plugin.
type ExploitInfo ¶
type ExploitInfo struct {
ExploitCount int `yaml:"exploit_count,omitempty"`
Sources []string `yaml:"sources,omitempty"`
HasWeaponized bool `yaml:"has_weaponized,omitempty"`
HighestMaturity string `yaml:"highest_maturity,omitempty"`
}
ExploitInfo captures exploit intelligence stored in memory.
type FindingRecord ¶
type FindingRecord struct {
Aliases []string `yaml:"aliases,omitempty"`
Package string `yaml:"package,omitempty"`
Ecosystem string `yaml:"ecosystem,omitempty"`
Discovery *DiscoveryInfo `yaml:"discovery,omitempty"`
Versions *VersionInfo `yaml:"versions,omitempty"`
Severity string `yaml:"severity,omitempty"`
SafeHarbour float64 `yaml:"safe_harbour,omitempty"`
Status string `yaml:"status,omitempty"` // not_affected | affected | fixed | under_investigation
Justification string `yaml:"justification,omitempty"`
ActionResponse string `yaml:"action_response,omitempty"`
ThreatModel *ThreatModel `yaml:"threat_model,omitempty"`
CWSS *CWSSData `yaml:"cwss,omitempty"`
Decision *Decision `yaml:"decision,omitempty"`
History []HistoryEntry `yaml:"history,omitempty"`
Source string `yaml:"source,omitempty"` // "vulnetix-sca" | "github"
Tool string `yaml:"tool,omitempty"` // sca | sast | iac | secrets | container | quality | license
Locations []Location `yaml:"locations,omitempty"`
LastSeenBranch string `yaml:"last_seen_branch,omitempty"`
LastSeenAt string `yaml:"last_seen_at,omitempty"`
// Enriched scan data — populated by vulnetix scan.
AffectedRange string `yaml:"affected_range,omitempty"`
IsMalicious bool `yaml:"is_malicious,omitempty"`
Confirmed bool `yaml:"confirmed,omitempty"`
Scores *ScoreData `yaml:"scores,omitempty"`
Exploits *ExploitInfo `yaml:"exploits,omitempty"`
Remediation *RemediationData `yaml:"remediation,omitempty"`
InCisaKev bool `yaml:"in_cisa_kev,omitempty"`
InEuKev bool `yaml:"in_eu_kev,omitempty"`
SourceFiles []string `yaml:"source_files,omitempty"` // manifest files where this vuln was introduced
PathCount int `yaml:"path_count,omitempty"` // number of dependency paths introducing this vuln
IntroducedPaths [][]string `yaml:"introduced_paths,omitempty"` // dependency chains e.g. [[direct-dep, intermediate, vuln-pkg]]
}
FindingRecord stores all triage data for a single vulnerability. This schema is shared with the Claude Code plugin SKILL files.
type HistoryEntry ¶
type HistoryEntry struct {
Date string `yaml:"date"`
Event string `yaml:"event"`
Detail string `yaml:"detail,omitempty"`
}
HistoryEntry is an append-only log entry for a finding.
type Location ¶ added in v3.0.2
type Location struct {
File string `yaml:"file"`
StartLine int `yaml:"start_line,omitempty"`
EndLine int `yaml:"end_line,omitempty"`
StartCol int `yaml:"start_col,omitempty"`
EndCol int `yaml:"end_col,omitempty"`
Snippet string `yaml:"snippet,omitempty"`
}
Location captures a code-level pointer for a finding: file + optional line/column range + optional snippet. Stored on FindingRecord.Locations.
type Memory ¶
type Memory struct {
Version string `yaml:"version"`
LastScan *ScanRecord `yaml:"last_scan,omitempty"`
History []ScanRecord `yaml:"history,omitempty"`
Findings map[string]FindingRecord `yaml:"findings,omitempty"` // triage findings keyed by CVE ID
SASTFindings map[string]SASTFindingRecord `yaml:"sast_findings,omitempty"` // SAST findings keyed by fingerprint
Environment *EnvironmentContext `yaml:"environment,omitempty"` // last-gathered env context
VDBQueries []VDBQuery `yaml:"vdb_queries,omitempty"` // recent VDB query log
// contains filtered or unexported fields
}
Memory is the top-level .vulnetix/memory.yaml structure.
func Load ¶
Load reads memory.yaml from the given .vulnetix directory. If the file does not exist, a fresh Memory is returned without error. If the file is corrupt, a fresh Memory is returned (non-fatal).
func (*Memory) GetFinding ¶
func (m *Memory) GetFinding(cveID string) *FindingRecord
GetFinding returns the triage finding for a given CVE ID, or nil if none exists.
func (*Memory) GetOpenFindings ¶
func (m *Memory) GetOpenFindings() map[string]FindingRecord
GetOpenFindings returns all findings that haven't reached a resolved state. "Open" means status is "under_investigation" or "affected" — i.e. not "not_affected" or "fixed". These are the findings that still need triage.
func (*Memory) GetOpenFindingsByTools ¶ added in v3.0.2
func (m *Memory) GetOpenFindingsByTools(tools []string) map[string]FindingRecord
GetOpenFindingsByTools returns open Findings filtered to the given tool tags. An empty list or a list containing "all" returns every open finding.
func (*Memory) GetOpenSASTFindingsByTools ¶ added in v3.0.2
func (m *Memory) GetOpenSASTFindingsByTools(tools []string) map[string]SASTFindingRecord
GetOpenSASTFindingsByTools returns open SAST findings filtered to the given tool tags. Since SASTFindings only ever holds Tool="sast" records, this is a no-op pass-through unless the filter explicitly excludes sast.
func (*Memory) MarkSASTFindingResolved ¶
MarkSASTFindingResolved marks a SAST finding as resolved by fingerprint.
func (*Memory) ReconcileFindings ¶
func (m *Memory) ReconcileFindings(currentCVEs map[string]bool) []StateChange
ReconcileFindings compares the set of CVE IDs found in the current scan against all existing findings with source "vulnetix-sca" in memory.
Findings present in memory but absent from the current scan are marked "fixed" (user remediated). Findings previously marked "fixed" that reappear in the current scan are marked "under_investigation" (regression).
Returns a list of state changes so the caller can generate VEX entries.
func (*Memory) ReconcileTool ¶ added in v3.2.0
func (m *Memory) ReconcileTool(ctx ReconcileContext) []StateChange
ReconcileTool walks Findings (and SASTFindings when Tool==sast) and flips status based on whether each record matches the current scan results, as described on ReconcileContext.
func (*Memory) RecordCategorizedFindings ¶ added in v3.0.2
func (m *Memory) RecordCategorizedFindings(tool string, findings map[string]FindingRecord)
RecordCategorizedFindings upserts findings tagged with a specific tool category (iac, secrets, container, quality, license). The map key is the finding identifier — a rule ID, secret fingerprint, license SPDX expression, etc. — chosen by the producer. Each FindingRecord must already have at least one Location populated; the function tags Tool and Status (default "under_investigation" for fresh records) and merges over existing entries.
func (*Memory) RecordEnrichedFindings ¶
func (m *Memory) RecordEnrichedFindings(findings []EnrichedFinding)
RecordEnrichedFindings upserts FindingRecords from enriched scan results. Each finding is keyed by CVE ID. Existing triage decisions are preserved — only enrichment data (scores, exploits, versions, source files) is updated.
func (*Memory) RecordReachability ¶
func (m *Memory) RecordReachability(vulnID string, evidence *ReachabilityEvidence)
RecordReachability stores a tree-sitter reachability scan result on an existing finding. Passing nil clears the field; passing an empty evidence struct also clears it (so a clean rescan doesn't leak stale matches). The function is a no-op when no finding exists yet — the caller is expected to RecordVulnLookup first.
func (*Memory) RecordSASTFindings ¶
func (m *Memory) RecordSASTFindings(findings []SASTFindingRecord)
RecordSASTFindings upserts SAST finding records. New findings get status "open" and first_seen set to now. Existing findings get last_seen updated.
func (*Memory) RecordScan ¶
func (m *Memory) RecordScan(rec ScanRecord)
RecordScan prepends rec to History, sets LastScan, and trims history to maxHistory. If rec.Timestamp is empty it is set to the current UTC time.
func (*Memory) RecordVDBQuery ¶
RecordVDBQuery prepends a VDB query to the log, capping at maxVDBQueries.
func (*Memory) RecordVulnLookup ¶
RecordVulnLookup upserts a FindingRecord from a VDB vuln response. It extracts the vulnId, aliases, severity, and scores from the opaque API response data. This is best-effort; missing fields are silently skipped.
func (*Memory) SetFinding ¶
func (m *Memory) SetFinding(cveID string, data FindingRecord)
SetFinding stores or updates triage data for a CVE ID.
func (*Memory) SetScanContext ¶ added in v3.2.0
func (m *Memory) SetScanContext(ctx *ScanContext)
SetScanContext stamps subsequent record writes with the given branch/path. Pass nil to clear. Reset between scan runs.
func (*Memory) UpdateEnvironment ¶
func (m *Memory) UpdateEnvironment(env *EnvironmentContext)
UpdateEnvironment replaces the stored environment context.
type ReachabilityEvidence ¶
type ReachabilityEvidence struct {
Direct []ReachabilityMatch `yaml:"direct,omitempty"`
Transitive []ReachabilityMatch `yaml:"transitive,omitempty"`
}
ReachabilityEvidence is the result of a tree-sitter reachability scan for a single finding. Direct matches live inside the installed-package folder; transitive matches are first-party (or other-dep) code paths that reach the vulnerable symbol.
type ReachabilityMatch ¶
type ReachabilityMatch struct {
File string `yaml:"file"`
Range string `yaml:"range"`
Query string `yaml:"query,omitempty"`
}
ReachabilityMatch is one tree-sitter query hit recorded against a file. The range is "start_line:end_line" (1-indexed, inclusive) matching the "n:n" convention used elsewhere in CLI output.
type ReconcileContext ¶ added in v3.2.0
type ReconcileContext struct {
Tool string
CurrentIDs map[string]bool
InstalledPkgs map[string]bool
Branch string
RootPath string
Verifier func(loc Location) (gone bool, reason string)
}
ReconcileContext drives ReconcileTool. Behaviour varies by Tool:
- sca / container: CurrentIDs is the set of CVE IDs in the current scan. InstalledPkgs is "<ecosystem>:<name>"; used to distinguish "dependency removed" from "patched upstream".
- sast / secrets / iac: CurrentIDs is the set of fingerprints emitted by the current scan. Verifier is consulted before flipping a record to `fixed` — if the on-disk evidence is still present (Verifier returns gone=false) the record is left untouched.
Records whose LastSeenBranch is non-empty and differs from ctx.Branch are skipped entirely — we never auto-resolve findings recorded on another branch during a scan of this one.
type RemediationData ¶
type RemediationData struct {
FixAvailability string `yaml:"fix_availability,omitempty"` // available | partial | no_fix
FixVersion string `yaml:"fix_version,omitempty"`
Actions []string `yaml:"actions,omitempty"`
}
RemediationData captures remediation info stored in memory.
type SASTFindingRecord ¶
type SASTFindingRecord struct {
RuleID string `yaml:"rule_id"`
RuleName string `yaml:"rule_name"`
Severity string `yaml:"severity"`
FirstSeen string `yaml:"first_seen"`
LastSeen string `yaml:"last_seen"`
Status string `yaml:"status"` // "open"|"resolved"|"suppressed"
ResolvedAt string `yaml:"resolved_at,omitempty"`
ArtifactURI string `yaml:"artifact_uri,omitempty"`
StartLine int `yaml:"start_line,omitempty"`
Fingerprint string `yaml:"fingerprint"`
Properties map[string]interface{} `yaml:"properties,omitempty"`
Tool string `yaml:"tool,omitempty"` // always "sast"; persisted for filter symmetry
Locations []Location `yaml:"locations,omitempty"`
LastSeenBranch string `yaml:"last_seen_branch,omitempty"`
LastSeenAt string `yaml:"last_seen_at,omitempty"`
}
SASTFindingRecord stores triage data for a single SAST finding, keyed by fingerprint in the SASTFindings map.
type ScanContext ¶ added in v3.2.0
type ScanContext struct {
Branch string
Path string
Timestamp string // RFC3339 UTC; if empty, writers fill with time.Now().
}
ScanContext is the per-scan metadata threaded into record writers so each finding remembers when and where it was last seen. Branch in particular is load-bearing for reconciliation: cross-branch scans must not auto-resolve findings recorded under a different branch.
type ScanRecord ¶
type ScanRecord struct {
Timestamp string `yaml:"timestamp"`
Path string `yaml:"path,omitempty"`
GitBranch string `yaml:"git_branch,omitempty"`
GitCommit string `yaml:"git_commit,omitempty"`
GitRemote string `yaml:"git_remote,omitempty"`
FilesScanned int `yaml:"files_scanned"`
Packages int `yaml:"packages"`
Vulns int `yaml:"vulns"`
Critical int `yaml:"critical"`
High int `yaml:"high"`
Medium int `yaml:"medium"`
Low int `yaml:"low"`
SBOMPath string `yaml:"sbom_path,omitempty"`
ScopeBreakdown map[string]ScopeStats `yaml:"scope_breakdown,omitempty"`
IDSRulesPath string `yaml:"ids_rules_path,omitempty"`
IDSRulesCount int `yaml:"ids_rules_count,omitempty"`
SASTRulesLoaded int `yaml:"sast_rules_loaded,omitempty"`
SASTFindingCount int `yaml:"sast_finding_count,omitempty"`
SARIFPath string `yaml:"sarif_path,omitempty"`
}
ScanRecord summarises one scan run.
type ScopeStats ¶
ScopeStats records package and vulnerability counts for a single scope bucket.
type ScoreData ¶
type ScoreData struct {
CVSSScore float64 `yaml:"cvss_score,omitempty"`
CVSSSeverity string `yaml:"cvss_severity,omitempty"`
EPSSScore float64 `yaml:"epss_score,omitempty"`
EPSSPercentile float64 `yaml:"epss_percentile,omitempty"`
EPSSSeverity string `yaml:"epss_severity,omitempty"`
CoalitionESS float64 `yaml:"coalition_ess,omitempty"`
CESSeverity string `yaml:"ces_severity,omitempty"`
SSVCDecision string `yaml:"ssvc_decision,omitempty"`
SSVCSeverity string `yaml:"ssvc_severity,omitempty"`
ThreatExposure float64 `yaml:"threat_exposure,omitempty"`
MaxSeverity string `yaml:"max_severity,omitempty"`
}
ScoreData captures all scoring sources for a vulnerability.
type StateChange ¶
type StateChange struct {
CveID string
Tool string
Package string
Ecosystem string
OldStatus string
NewStatus string
Comment string
Finding FindingRecord
}
StateChange describes a finding whose status changed during reconciliation.
type ThreatModel ¶
type ThreatModel struct {
Techniques []string `yaml:"techniques,omitempty"`
Tactics []string `yaml:"tactics,omitempty"`
AttackVector string `yaml:"attack_vector,omitempty"`
AttackComplexity string `yaml:"attack_complexity,omitempty"`
PrivilegesRequired string `yaml:"privileges_required,omitempty"`
UserInteraction string `yaml:"user_interaction,omitempty"`
Reachability string `yaml:"reachability,omitempty"`
Exposure string `yaml:"exposure,omitempty"`
ReachabilityEvidence *ReachabilityEvidence `yaml:"reachability_evidence,omitempty"`
}
ThreatModel holds MITRE ATT&CK-derived threat modelling data.
type VDBQuery ¶
type VDBQuery struct {
Timestamp string `yaml:"timestamp"`
Command string `yaml:"command"` // e.g. "vuln", "fixes", "exploits"
Args string `yaml:"args,omitempty"` // e.g. "CVE-2021-44228"
APIVersion string `yaml:"api_version,omitempty"`
}
VDBQuery records a single VDB API query in the memory log.