memory

package
v3.12.3 Latest Latest
Warning

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

Go to latest
Published: Jun 4, 2026 License: AGPL-3.0 Imports: 7 Imported by: 0

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

View Source
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.

View Source
const (
	// FileName is the basename of the memory file inside .vulnetix/.
	FileName = "memory.yaml"
)

Variables

AllTools is the canonical list of tool tags persisted in memory.

Functions

func Save

func Save(vulnetixDir string, m *Memory) error

Save writes m to memory.yaml inside vulnetixDir, creating the directory if needed.

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

func Load(vulnetixDir string) (*Memory, error)

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

func (m *Memory) MarkSASTFindingResolved(fingerprint string)

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

func (m *Memory) RecordVDBQuery(q VDBQuery)

RecordVDBQuery prepends a VDB query to the log, capping at maxVDBQueries.

func (*Memory) RecordVulnLookup

func (m *Memory) RecordVulnLookup(vulnID string, data interface{})

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

type ScopeStats struct {
	Packages int `yaml:"packages"`
	Vulns    int `yaml:"vulns"`
}

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.

type VersionInfo

type VersionInfo struct {
	Current       string `yaml:"current,omitempty"`
	CurrentSource string `yaml:"current_source,omitempty"`
	FixedIn       string `yaml:"fixed_in,omitempty"`
	FixSource     string `yaml:"fix_source,omitempty"`
}

VersionInfo tracks package versions relevant to a finding.

Jump to

Keyboard shortcuts

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