KRIS RACETTE
Verified · Live Open Source · Apache 2.0 Upstream PR · pending
Open Source • Personal Project • Privacy-First Security Tooling
🛡️

OPENANT + OLLAMA
LOCAL SAST

LLM-assisted vulnerability scanning — fully local, no code leaves the box

I built a first-class Ollama adapter for OpenAnt (open-source SAST from Knostic) so scans run against local models. No cloud. No API keys. No source code leaving the machine. Verified end-to-end: both planted SQL injection findings (CWE-89) detected via local mistral-small3.2 on commodity hardware.

My Story

LLM-assisted security tooling is having a moment. Tools like OpenAnt, Semgrep's Assistant, and a dozen new entrants are using foundation models to cut false positives, explain findings, and triage the noise that traditional SAST tools produce. The pitch is great: find more, explain more, miss less.

The catch is in the data flow. Most of these tools assume a cloud LLM — OpenAI, Anthropic, Google. That means your source code gets shipped to a third-party API for analysis. For most teams, that's already uncomfortable. For some teams — defence, healthcare, finance, legal, infrastructure operators — it's a hard no. The code physically cannot leave the perimeter.

I hit this wall myself. OpenAnt is one of the better open-source LLM-assisted SAST tools out there (Apache 2.0, from Knostic), but it shipped with provider adapters for the usual cloud suspects. No Ollama. No local. No "bring your own model".

So I built one. A clean, first-class Ollama adapter that slots into OpenAnt's existing provider architecture — because Ollama exposes an OpenAI-compatible endpoint, the integration is mostly configuration, not reinvention. Wizard support, model registry entries, contract tests, documentation. The whole thing is structured as an upstream contribution, not a fork. Privacy-first by default.

The verification run was the part that mattered. I scanned a planted-vulnerability test repo with mistral-small3.2 running locally on my workstation — and both planted SQL injection findings (CWE-89) came back correct. No cloud calls. No keys leaving the box. Local model, real findings, real accuracy.

How It Works

Step 1 — Install OpenAnt. git clone the upstream, install dependencies, run the setup wizard. Standard SAST install.

Step 2 — Choose Ollama as the provider. The setup wizard now lists Ollama as a first-class provider option. API key is optional (it's local — http://localhost:11434/v1). Connectivity probe runs at setup; sensible model defaults are suggested per tier.

Step 3 — Pull a model. Whatever you want, locally. ollama pull mistral-small3.2. Chat variants only — base completion models reject /chat/completions endpoints and the wizard will warn you about that.

Step 4 — Warm up. Large models (15 GB+) take several minutes to load on first inference. Run a small prompt before kicking off the scan — much cheaper than discovering the timeout mid-job.

Step 5 — Scan. Point OpenAnt at your repo. The local model handles LLM-assisted triage, false-positive filtering, and explanation. Source code never leaves the box. The adapter logs every call so you can audit what's being sent to the model — and the answer is: only what OpenAnt already sends to any provider, which is the function being analysed, never the full file graph.

Step 6 — Verify. For production deployments, run against a known-vulnerability corpus first. The same planted-finding rig I used to validate the adapter is reproducible — small SQLi-prone file, run the scan, confirm both findings come back. That's the test that proves the pipeline works on your hardware, your model, your environment.

What I Verified

CWE-89 · SQL Injection · Planted

✓ Detected — Local Ollama model (mistral-small3.2, 15 GB) identified both planted SQL injection findings in the test corpus. Verifier confirmed against planted sink/source pairs. Zero network egress beyond the local machine.

Environment

  • Provider: ollama
  • Model: mistral-small3.2 (15 GB local)
  • Endpoint: http://localhost:11434/v1
  • Network: local-only (no cloud calls)
  • API key: none required

Things That Will Bite You

Base completion models break. Pick chat/instruct variants. The adapter calls /chat/completions; completion-only models return errors. Document this somewhere visible in your runbook.

Cold loads. A 15 GB model on first inference can take several minutes. Warm up before demos. Very large models (70B+) can wedge a workstation entirely — size your model to your hardware.

Probe timeouts. Default OpenAnt probe timeouts are tuned for cloud round-trips. Cold loads blow past them. Bump the timeout in your setup, or document the warm-up step clearly.

Model choice matters more than you'd think. Code-specialised models (qwen3.8, deepseek-coder-v2) substantially outperform general-purpose models on vulnerability reasoning. Benchmark on your own corpus before you commit.

Where This Fits

Same architecture applies anywhere you want LLM-assisted tooling without sending data to a vendor cloud:

  • Dependency review — CVE matching, version comparison, exploit-context analysis
  • Secret scanning — pattern detection plus LLM triage of false positives, fully local
  • Threat-modelling copilots — STRIDE-style analysis against local architecture docs
  • Code-review agents — PR review with explanation, all inference on your machine
  • Compliance evidence — generate audit-ready documentation without the code ever leaving your perimeter

Status & Next Steps

  • Adapter builtopenant-core/utilities/llm/providers/ollama.py
  • Wizard integration — Ollama as a first-class provider choice
  • Contract tests — consistent with upstream provider test pattern
  • Documentation — install, model selection, warm-up behaviour
  • End-to-end verified — planted SQLi findings detected via local model
  • Upstream PR — pending, link goes live once merged to knostic/OpenAnt