Documentation
¶
Overview ¶
Package llm provides an optional, pluggable LLM-backed reviewer that adjudicates lower-confidence taint findings and discards likely false positives. It is the release valve for the project's "perfect signal/noise" goal: the deterministic analysis stays recall-oriented, and this stage trims residual false positives on the findings the engine was least sure about.
This file is deliberately dependency-free (no Anthropic SDK import) so the filtering/prompt/parse logic is unit-testable on its own. The concrete Anthropic-backed Reviewer lives in anthropic.go.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AnthropicReviewer ¶
type AnthropicReviewer struct {
// contains filtered or unexported fields
}
AnthropicReviewer is a Reviewer backed by the Anthropic Messages API. It is the concrete, pluggable implementation of the (otherwise dependency-free) review pipeline in review.go.
When a ToolBox is attached (WithTools), the reviewer runs an AGENTIC loop (LLM-4): it offers Claude read-only tools — read a file range, resolve a canonical function name to its source, grep the tree — so it can trace the flow, read the callee/sanitizer/route, and adjudicate an interprocedural finding the way a human triager would, instead of guessing from a fixed snippet. Without a ToolBox it falls back to the one-shot prompt→verdict.
func NewAnthropicReviewer ¶
func NewAnthropicReviewer() *AnthropicReviewer
NewAnthropicReviewer builds a reviewer using a fast, inexpensive default model (claude-haiku-4-5) — the review task is one-sentence JSON triage over a finding, run per-finding at scale, so a Haiku-class model keeps a large scan affordable and quick (LLM-5). Override with GODZILLA_LLM_MODEL to upgrade to Opus for harder adjudication. Credentials are resolved by the SDK from ANTHROPIC_API_KEY or an `ant auth` profile; a missing credential surfaces as a per-review error, which Filter treats as fail-open (the finding is kept, never silently dropped).
func (*AnthropicReviewer) Review ¶
func (a *AnthropicReviewer) Review(ctx context.Context, f analysis.Finding, codeContext string) (Verdict, error)
Review adjudicates a single finding. With a ToolBox attached it runs the agentic tool-use loop; otherwise it makes the one-shot call.
func (*AnthropicReviewer) WithTools ¶
func (a *AnthropicReviewer) WithTools(tb ToolBox) *AnthropicReviewer
WithTools attaches a ToolBox, switching the reviewer into agentic mode. It returns the receiver for chaining. Passing a nil ToolBox keeps one-shot mode.
type FileToolBox ¶
type FileToolBox struct {
// contains filtered or unexported fields
}
FileToolBox is the default ToolBox: it reads from the real filesystem (fenced to the scan root) and resolves function names against the analyzed gIR program. A nil FileToolBox is safe — its methods return an explanatory error, so a reviewer configured without one degrades to no-agency rather than panics.
func NewFileToolBox ¶
func NewFileToolBox(prog *ir.Program, root string) *FileToolBox
NewFileToolBox builds a toolbox over the analyzed program and scan root. root may be a file or a directory; file access is confined to it (a single-file scan confines to that file's directory).
func (*FileToolBox) FindFunction ¶
func (tb *FileToolBox) FindFunction(canonicalName string) (string, error)
FindFunction resolves a canonical function name (exact, or a unique case-insensitive substring match) to its source location and a snippet around its declaration — so the reviewer can read the callee of a tainted call, a sanitizer body, etc.
func (*FileToolBox) Grep ¶
func (tb *FileToolBox) Grep(pattern string, maxHits int) (string, error)
Grep searches the scanned tree for a regular expression and returns up to maxHits "file:line: text" matches. It skips the same vendored/build/binary directories the scanner does and bounds total output.
func (*FileToolBox) ReadFileRange ¶
func (tb *FileToolBox) ReadFileRange(path string, start, end int) (string, error)
ReadFileRange returns lines [start,end] (1-based, inclusive) of a file within the scan root, each prefixed with its line number. The range is clamped to the file and bounded in size.
type OpenAIReviewer ¶
type OpenAIReviewer struct {
// contains filtered or unexported fields
}
OpenAIReviewer is a Reviewer backed by any OpenAI-compatible /chat/completions endpoint (LLM-9): OpenAI itself, or a local/offline server such as Ollama, vLLM, or llama.cpp — enabling the FP-backstop in air-gapped or data-residency- constrained CI where the Anthropic API is unreachable. It speaks the API over plain net/http (no SDK dependency) and reuses the shared prompt/verdict logic.
Configuration (all optional except a base URL for non-OpenAI hosts):
- GODZILLA_LLM_BASE_URL or OPENAI_BASE_URL — endpoint base (default https://api.openai.com/v1); point it at http://localhost:11434/v1 for Ollama.
- OPENAI_API_KEY — bearer token (local servers usually ignore it).
- GODZILLA_LLM_MODEL — model id (default gpt-4o-mini).
func NewOpenAIReviewer ¶
func NewOpenAIReviewer() *OpenAIReviewer
NewOpenAIReviewer builds an OpenAI-compatible reviewer from the environment.
type ReviewConfig ¶
type ReviewConfig struct {
Concurrency int // max concurrent reviews (default 8)
Timeout time.Duration // per-review timeout (0 = none; default 30s)
MaxReviews int // cap on reviews per pass (0 = unlimited; default 200)
}
ReviewConfig bounds a review pass so a large scan cannot stall or cost unboundedly (LLM-5): reviews run through a bounded worker pool, each under a per-call timeout, capped at a maximum number per scan (excess findings are kept unreviewed — fail open).
func DefaultReviewConfig ¶
func DefaultReviewConfig() ReviewConfig
DefaultReviewConfig returns the tuned defaults, so a pathological scan degrades to "some findings kept unreviewed" rather than an unbounded bill or stalled pipeline.
type ReviewStats ¶
type ReviewStats struct {
Reviewed int // findings actually sent to the reviewer
Suppressed int // findings the reviewer judged false positives (retained, flagged)
Errors int // reviewer errors (finding kept unreviewed, fail-open)
LowContext int // findings kept unreviewed because no code context was available
Skipped int // findings past the per-scan review cap (kept unreviewed, fail-open)
FirstErr error // first reviewer error, for a single actionable message
}
ReviewStats summarizes one review pass so a nondeterministic model's effect on the gate is never invisible.
func Filter ¶
func Filter(ctx context.Context, r Reviewer, findings []analysis.Finding, reviewUpTo analysis.Confidence) ([]analysis.Finding, ReviewStats)
Filter reviews every finding whose Confidence is at or below reviewUpTo. A finding the reviewer judges a false positive is RETAINED but marked Suppressed (with the reviewer's reason), not deleted — auditability over silent deletion. Findings above the threshold are passed through unreviewed.
Two safety properties hold. Fail-open: on a reviewer error the finding is kept unreviewed — an LLM/network failure must never drop a real finding. Never-blind: a finding with no readable code context is kept unreviewed rather than judged on nothing, so an empty snippet can't cause a suppression.
It returns all findings (surviving ones plus the suppressed-and-flagged ones) and a ReviewStats describing the pass.
func FilterWithConfig ¶
func FilterWithConfig(ctx context.Context, r Reviewer, findings []analysis.Finding, reviewUpTo analysis.Confidence, cfg ReviewConfig) ([]analysis.Finding, ReviewStats)
FilterWithConfig is Filter with an explicit ReviewConfig. Output order is preserved; findings past cfg.MaxReviews are kept unreviewed (fail open, counted in Skipped). Filter's two safety properties still hold.
type Reviewer ¶
type Reviewer interface {
Review(ctx context.Context, f analysis.Finding, codeContext string) (Verdict, error)
}
Reviewer adjudicates a finding, given some surrounding source context, and returns whether it judges the finding to be a false positive.
func NewReviewer ¶
NewReviewer selects the reviewer backend from GODZILLA_LLM_PROVIDER (LLM-9): "openai" uses an OpenAI-compatible endpoint (one-shot; covers local/offline servers), anything else (the default) uses the Anthropic reviewer with agentic tools over the analyzed program. The Anthropic path also honors ANTHROPIC_BASE_URL for an Anthropic-compatible proxy.
type ToolBox ¶
type ToolBox interface {
ReadFileRange(path string, start, end int) (string, error)
FindFunction(canonicalName string) (string, error)
Grep(pattern string, maxHits int) (string, error)
}
ToolBox is the read-only capability set the agentic reviewer (LLM-4) can call to gather evidence before adjudicating a finding: read a range of a file, resolve a canonical function name to its source, or grep the scanned tree. It is deliberately dependency-free (no Anthropic SDK) so the tools and their dispatch are unit-testable; the SDK tool-use loop that drives them lives in anthropic.go. Every capability is read-only and confined to the scan root.
type ToolSpec ¶
ToolSpec describes one reviewer tool for the model: its name, purpose, and JSON-schema input shape. anthropic.go converts these to SDK tool params, so the tool catalog is declared once, here, dependency-free.
func ReviewToolSpecs ¶
func ReviewToolSpecs() []ToolSpec
ReviewToolSpecs is the catalog of read-only tools offered to the agentic reviewer.
type Verdict ¶
type Verdict struct {
FalsePositive bool
Reason string
Confidence float64 // model self-confidence 0..1 (0 if not provided)
Exploitability string // one-sentence exploitability note (optional)
}
Verdict is a reviewer's judgment about a single finding. Beyond the binary false-positive decision, it can carry the model's self-confidence and a one-sentence exploitability assessment (LLM-7) — surfaced on a KEPT finding so a developer sees the reviewer's reasoning, not just a pass/drop.