How T3MP3ST harnesses guarded Fable 5 to find bugs
TL;DR: I used T3MP3ST's vulnerability-discovery arm and fourteen rivals to learn what makes a vulnerability-discovery agent effective. T3MP3ST uses a clever trick to harness Fable 5 for vulnerability discovery without triggering safeguards. But the recipe for fundamental success is a real code graph, tight context management, and an oracle that runs the exploit.
Last week my walkthrough of Pliny's T3MP3ST covered what makes a capable offensive agent. Also OpenAI just shared how things can get wrong if such agents are not properly isolated.
But let's unpack the second arm of T3MP3ST that finds vulnerabilities in source code and try to understand what makes a great agent for vulnerability discovery.
First, there is no shortage of open-source LLM-powered vulnerability-discovery frameworks. I found more than 40, but kept only 14 that are active on GitHub. They range from a full pipeline that builds a code graph and runs its exploits in a sandbox to a single prompt with a filter on top.
| # | Framework | Stars | What it is |
|---|---|---|---|
| 1 | lintsinghua/DeepAudit | 6.7k | Multi-agent code-audit system with sandboxed PoC verification. |
| 2 | anthropics/claude-code-security-review | 5.6k | GitHub Action where Claude runs diff-aware security analysis of pull requests. |
| 3 | larlarua/AutoCVE | 1.1k | Agent-driven CVE discovery, source audit plus verification and report. |
| 4 | arm/metis | 808 | Arm's agentic deep security code review across 13 languages. |
| 5 | evilsocket/audit | 754 | 8-stage vulnerability-discovery agent modeled on Project Glasswing. |
| 6 | hadriansecurity/OpenHack | 721 | White-box review, recon to prove-or-reject triage, runs in Claude Code, Codex, Cursor. |
| 7 | knostic/OpenAnt | 681 | Stage 1 detects, Stage 2 attacks and verifies. Multi-language. |
| 8 | kpolley/redai | 335 | Scanner agents flag findings, validator agents prove them in a live environment. |
| 9 | adshao/flounder | 317 | Autonomous auditor that maps attack surface and constructs exploit paths. |
| 10 | openhackai/OpenHack | 299 | Agentic scanner, recon to hunting to validation to verification. |
| 11 | weareaisle/nano-analyzer | 297 | Minimal single-file LLM scanner biased to C and C++ memory safety. |
| 12 | Agent-Field/sec-af | 176 | Auditor that proves exploitability with a verdict, a trace, and evidence. |
| 13 | theteatoast/local-vuln-research-pipeline | 163 | Fully local pipeline that taint-validates every source-to-sink path. |
| 14 | fuzzingbrain/afc-crs | 122 | DARPA AIxCC entry, fuzzing plus an LLM to find and patch, every finding verified. |
Cutoff applied: 100+ GitHub stars and a commit within the last six months. Total: 14 frameworks.
How T3MP3ST works for vulnerability discovery
The arm runs three stages: two model-free static passes that pick and rank the code, a two-model LLM loop that does the hunting, and a final synthesis.
The two-model loop. The main bet of the framework is on Fable 5, a strong frontier model. The system is built to extract the offensively useful code analysis from Fable 5 without ever showing it the offensive framing, while Opus 4.8 does the actual security reasoning. So Opus 4.8 knows the attack goal and the full source and breaks that goal down for a worker on Fable 5 that sees only code snippets and benign tasks like computing struct sizes, listing every bounds check, and tracing data flow.
Two no-LLM static passes feed that loop.
Selector, no LLM: build the code graph. It crawls the repo for source files and parses each into one block per function, method, or class. It then builds a call graph, marks the entry points, and determines functions' reachability.
The idea is right, but the execution is overly simplistic. It resolves calls by bare name so it links unrelated functions that share a name and misses calls into imported or library code. Entry points are guessed from a Flask-style decorator or a name prefix like handle or get_, making it largely ineffective for Go, Java, or JavaScript. Reachability is just a breadth-first walk from the entry points over the edges.
Classifier, no LLM: rank the functions. It uses regexes to label each function by exposure, from external entry point down to neutral, then scores it, adding ten points for each dangerous call in its body such as exec, eval, or a shell or network call, plus a bonus for sitting close to an entry point. The top candidates survive to the next step.
Synthesizer prepares the findings. The orchestrator consolidates the rounds into a structured result: the vulnerabilities, the unresolved gaps, a one-paragraph attack-surface summary, and a confidence score. No oracle confirms any of it.
I then looked at other frameworks to find ideas that make a great vulnerability-discovery agent.
Top 3 design ideas
- A real code graph, and the reachability and taint you compute on it. Parse the code, resolve calls and imports, and build the call graph from the actual syntax, ideally with CodeQL or Joern. On that graph you answer the two questions that matter: can external input reach a sink (reachability), and does untrusted data actually reach it unsanitized (taint). Make it hybrid by adding an LLM pass that recovers the missed entry points and re-seeds the search. OpenAnt does exactly this entry-point recovery, and LVRP builds the taint half, following every source-to-sink path. And whether you enumerate every path on that graph or just rank a sample sets your coverage guarantee: full enumeration earns its compute on high-assurance targets like a kernel or a browser, and is overkill elsewhere.
- The harness is context management: it decides what code the model sees. It matters most on large codebases. A weak harness hands a frontier model the raw code, or worse, the wrong snippets. A strong one curates and prioritizes. It shows the whole path, from where untrusted input enters to the dangerous operation, with any check along the way. OpenAnt walks the call graph to assemble that path. It also uses the graph, taint, and sanitizer rules to settle most paths and reserve the LLM for the ambiguous cases.
- An oracle, matched to the bug class. Memory-safety bugs crash, so the proof is a fuzzer running a sanitized build until it does, which is what FuzzingBrain does. Logic, injection, and access-control bugs never crash, so a behavioral check is needed, such as returning the contents of /etc/passwd, which is what DeepAudit and OpenAnt do by running a generated exploit in a sandbox. When nothing can be run, all that is left is an LLM weighing static evidence. That happens when the target will not build, as with hardware, firmware, or legacy code, or when the flaw has no runnable trigger, as with a weak cipher or a hardcoded secret. That is what Metis does.
Sources:
- DeepAudit (lintsinghua)
- claude-code-security-review (anthropics)
- AutoCVE (larlarua)
- metis (arm)
- audit (evilsocket)
- OpenHack (hadriansecurity)
- OpenAnt (knostic)
- redai (kpolley)
- flounder (adshao)
- OpenHack (openhackai)
- nano-analyzer (weareaisle)
- sec-af (Agent-Field)
- local-vuln-research-pipeline (theteatoast)
- afc-crs (fuzzingbrain)