llm

package
v0.9.0 Latest Latest
Warning

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

Go to latest
Published: Aug 23, 2026 License: MIT Imports: 21 Imported by: 0

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.

func (*OpenAIReviewer) Review

func (o *OpenAIReviewer) Review(ctx context.Context, f analysis.Finding, codeContext string) (Verdict, error)

Review adjudicates one finding via a single chat-completion request.

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

func NewReviewer(tb ToolBox) Reviewer

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

type ToolSpec struct {
	Name        string
	Description string
	InputSchema map[string]any
}

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.

Jump to

Keyboard shortcuts

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