# OpenAnt sends every scan through two LLM stages, and its zero-config path only speaks Anthropic

> An Apache 2 licensed vulnerability discovery harness from Knostic, built as a Go CLI on top of a Python core. It supports nine languages, routes each pipeline phase to its own model, and leaves the token cost numbers to a blog post rather than the project file.

**knostic/OpenAnt** — OpenAnt from Knostic is the leading open source LLM-based vulnerability discovery product, helping defenders proactively find verified security flaws while minimizing both false positives and false negatives. Stage 1 detects. Stage 2 attacks. What survives is real.

- Repository: https://github.com/knostic/OpenAnt
- Website: https://www.knostic.ai/openant
- Stars: 756 · Forks: 114
- Language: Python
- License: Apache-2.0
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/knostic-openant

## Detection first, then attack, and only the survivors are reported

The design is two stages, and the project's own summary of it is three sentences long: stage 1 detects, stage 2 attacks, what survives is real. That is the whole filtering argument. A finding has to pass a detection pass and then survive an attack pass before it counts, which is a different shape from a scanner that reports everything it matched.

The research paper behind it is titled OpenAnt: LLM-Powered Vulnerability Discovery Through Code Decomposition, Adversarial Verification, and Dynamic Testing, by Nahum Korda and Gadi Evron, and is on arXiv under 2606.19149. Three mechanisms in that title map onto the pipeline: decomposition of the code before analysis, verification framed as adversarial, and dynamic testing rather than reading alone.

The limits of that arrangement are not in the project file. Technical details, limitations, and token costs are all pointed at a Knostic blog post instead, so the repository states what it does and refers you elsewhere for what it costs and where it breaks. Two other paths out of the repository are named the same way: a submission form for having your own repository scanned at no cost, and the vendor's own product page.

One framing line is worth quoting because it is unusual in a security tool: it describes itself as the first open source LLM-based vulnerability discovery product, now called a harness.

## Three languages are listed without a beta marker and six carry one

The supported list is nine entries long, and the markers are not subtle. Go, Python and C/C++ appear on their own lines. The other six each end with the word beta: JavaScript/TypeScript, PHP, Ruby, Zig, Swift and Rust.

That split is not an accident of formatting. The project states that it started as a research project and that, as new capabilities are developed, they are often released as beta. Six of nine is a lot of beta, and the ones carrying it are the mainstream web languages. A team running a PHP or TypeScript service would be on the beta side of that line for every scan.

The list is also the honest measure of parser coverage. There is an adding-a-parser.md in the repository root, which is where the boundary sits: adding a language means writing a parser, and the marker tells you which parsers are still being worked on. Nothing in the list says how much a beta parser misses, so the flag is the only signal available at the language-selection step.

## The no-configuration path is compiled into the binary and speaks only Anthropic

Six model adapters ship with the tool: anthropic as the reference adapter, plus openai, google, bedrock, openrouter and ollama. The wizard reaches all of them. The shortcut reaches one.

```bash
openant scan /path/to/repo
```

Running a scan with no other arguments uses a configuration called openant-default, compiled into the binary so that no config.json is needed. Its contents are stated in one line: Claude Opus 4.6 for the detection phases, Sonnet 4 for the rest. So the path of least resistance, which is also the path a first-time user takes, is a single vendor with two named models, while the other five adapters require a config file that the wizard writes for you.

The wizard itself is `openant setup llm`. You name the config, pick a provider per pipeline phase, enter each provider's key once, and the wizard probes every unique provider and model pair with a one-token request before writing ~/.config/openant/config.json. Scans then point at a named config with --llm-config.

Its defaults reflect a per-phase recommendation: stronger reasoning models for detection, verification and reachability review, lighter ones for context, report and test generation. Any of those answers can be overridden, which is what makes the wizard worth the extra step when the default pair is wrong for a repository.

## Three adapters say your existing subscription does not pay for the key

The adapter table carries a billing column that has nothing to do with models. The anthropic row says the key is not included in Claude Pro or Max subscriptions and is billed separately. The openai row says the same for ChatGPT and Codex. The google row says the same for Gemini Advanced. Three of the six routes into this tool require a separate bill from the assistant you may already pay for.

The other three work differently. bedrock takes no api_key at all: credentials come from AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY or from a profile in ~/.aws, the region from AWS_REGION, and the model IDs are inference profiles rather than plain model names, which have to be enabled under Model access in the console and can be listed with aws bedrock list-inference-profiles. openrouter reads OPENROUTER_API_KEY as well as the wizard entry, and routes to many providers on one key and one prepaid balance. ollama runs against a local server with no key, a placeholder sent automatically, and a base URL defaulting to http://localhost:11434/v1.

Cost reporting follows the same split. Local Ollama inference is reported as $0, which makes it the only route where the scan has no per-token line item, and the reason the project points at a blog post for token costs is that the other five routes bill per phase.

## Bedrock skips the probe, Ollama sends a placeholder, and small local models fail the tool loop

The wizard probes each provider and model pair with a one-token request before it writes the config, which is a sensible way to catch a wrong key early. Two adapters need exceptions. Bedrock is offered by the wizard with the key left blank and the probe skipped, since the credential chain decides whether it works. Ollama is offered with no key either, and a placeholder is sent automatically, so the probe checks that a local server is answering rather than that a credential is valid.

Ollama has a second requirement that the table does not put in the same column. Models have to be pulled first with ollama pull, and the model IDs are exactly what ollama list shows, with no aliasing. That makes the local route the least portable: a config that works on one machine depends on what that machine has pulled.

All six adapters support tool calling, and that capability is what decides whether a provider can run the phases that use the agentic tool-use loop, named enhance and verify. The note for Ollama is direct about the limit: pick a tools-capable model for those phases, because very small local models may not handle tool calls reliably. A local model that answers the probe can still fail the phases the tool loop depends on, and the probe will not tell you.

## Building the CLI means a Go build and a symlink into /usr/local/bin

Local setup is three commands and one constraint.

```bash
cd apps/openant-cli && make build
```

Go 1.25 or newer is required, and the output lands at apps/openant-cli/bin/openant. The next step puts it on your PATH:

```bash
ln -sf "$(pwd)/apps/openant-cli/bin/openant" /usr/local/bin/openant
```

The command uses $(pwd), so it has to be run from the repository root, which the setup notes say explicitly. There is no install script, no package manager entry and no container recipe for the CLI; the local install is a build plus a symlink into a system directory.

The language split is the other thing to notice. The repository is catalogued as Python, and the shared code sits under libs/openant-core, while the binary you build and symlink is Go, living in apps/openant-cli. Two languages, two directories, one command. The provider guides are shipped as documents beside the code, at paths like libs/openant-core/utilities/llm/providers/BEDROCK.md, which is where the details for each adapter live instead of in the project file.

## A run log sits in the root next to the files that redact what gets published

The top level of the repository contains runA-388b.log, which is a run log kept in version control with a name that reads like a machine-generated identifier. Alongside it are .gitleaks.toml for secret scanning, .publish-exclude, and .publish-forbidden-strings.

Those three files together describe a publishing guard: something in the pipeline decides what may leave and blocks strings that must not. For a tool whose whole job is reading other people's repositories, secrets are the obvious hazard, and the guard is built into the repository rather than left to the reader's judgement about what a scan output may contain.

The rest of the root is a working project rather than a package. ARCHITECTURE.md and CHANGELOG.md sit next to adding-a-parser.md, which is the entry point for a new language, plus renovate.json for dependency updates, and apps/, libs/, config/, scripts/ and assets/ as the working directories. There are no GitHub releases for the project, so CHANGELOG.md is the version history, and the absence is worth knowing before you look for a download.

## The configuration section stops one word into its first sentence

The last part of the project file covers hand-authored configuration. It explains that the wizard writes ~/.config/openant/config.json but that you can edit the file directly too, and then the sentence ends mid-word: every llm-config must li, and nothing follows.

So the one part of the documentation that would tell you the constraints on a config you write by hand, what every llm-config must contain, is the part that does not finish. The wizard output is described in detail, and the six adapters are documented in detail, and the sentence that would state the schema of the file ends at two letters.

This is the shape of the project's documentation overall. The adapters, the billing notes, the per-phase defaults, and the free scanning route are all specific and checkable. The cost figures, the limitations, and the config schema are all somewhere else: a blog post for the first two, and no text at all for the third. Reading carefully means following those three exits, and one of them does not lead anywhere.

## Conclusion

OpenAnt belongs on code you own or have written permission to test. The path the project points at is your own repository, or handing the repository to Knostic's free scanning service. Before running it on anything else, check which of the nine languages are still beta, since six of them are, and read the linked blog post for the token costs, because the project file carries none. Budget separately for the provider key: three adapters state plainly that an existing subscription does not cover it. Ollama is the route that reports no cost, and it is also the one that needs a tool-capable model for the enhance and verify phases.

## FAQ

### What is OpenAnt and how do its two stages work?

It is an LLM-based vulnerability discovery harness from Knostic, released under the Apache 2 license. Stage 1 detects and stage 2 attacks, so a finding has to survive an attack pass before it is reported. The underlying paper covers code decomposition, adversarial verification, and dynamic testing.

### Which languages does OpenAnt support today?

Nine are listed. Go, Python and C/C++ appear without a marker, while JavaScript/TypeScript, PHP, Ruby, Zig, Swift and Rust are each marked beta. The project states that new capabilities are often released as beta.

### Which model providers can OpenAnt use?

Six adapters ship with it: anthropic as the reference adapter, plus openai, google, bedrock, openrouter and ollama. All of them support tool calling, so any of them can drive the enhance and verify phases that use the agentic tool-use loop.

### Does OpenAnt cost money to run?

It depends on the adapter. The table states that anthropic, openai and google keys are not included in Claude Pro or Max, ChatGPT or Codex, or Gemini Advanced subscriptions and are billed separately, while local Ollama inference is reported at zero cost. Token costs are covered in a Knostic blog post linked from the project.

### How do I build and configure OpenAnt locally?

Build the CLI with `cd apps/openant-cli && make build` on Go 1.25 or newer, then symlink apps/openant-cli/bin/openant onto your PATH from the repository root. Run `openant setup llm` to write a config, or use `openant set-api-key` to fall back on the openant-default configuration compiled into the binary.

## Sources

- [Issues](https://github.com/knostic/OpenAnt/issues)
- [knostic/OpenAnt on GitHub](https://github.com/knostic/OpenAnt)
- [License: Apache-2.0](https://github.com/knostic/OpenAnt/blob/master/LICENSE)
- [Project website](https://www.knostic.ai/openant)
- [README](https://github.com/knostic/OpenAnt/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/knostic-openant
