# Circom-Auditor: Open-Source Skills for Finding Vulnerabilities in Circom Code

- **Authors**: Stefanos Chaliasos, Hao Pham, False Witness Team
- **Date**: August 05, 2026
- **Tags**: security, AI, audit, zk, circom, tools, announcement
Over the past months we have been writing about using AI to find vulnerabilities in cryptographic code: in [Cloudflare's CIRCL](https://blog.zksecurity.xyz/posts/circl-bugs/), in [OpenVM's zkVM](https://blog.zksecurity.xyz/posts/openvm-bugs/), and in [Bron Labs's MPC library](https://blog.zksecurity.xyz/posts/bron-bugs/), all collected in our [AI meets Cryptography](https://blog.zksecurity.xyz/series/ai-meets-cryptography/) series.
In parallel, we have been building and improving [zkao](https://zkao.io/), our AI auditor that runs continuously on cryptographic code until the deep bugs surface (it recently got a [big 2.0 release](https://blog.zksecurity.xyz/posts/zkao-2-0/)).

Looking at more established security fields, one thing stood out as missing from ZK development: open-source skills that act as a first line of defense for developers and auditors alike.
Something cheap and quick you can run on your own code before anyone else looks at it.
Smart contract security already has this: [Pashov Audit Group's skills](https://github.com/pashov/skills) showed how much impact a well-curated set of agent skills can have, and zk-skills is directly inspired by their work; credit to them for paving the way.
ZK had nothing comparable. Until today.

We are releasing [zk-skills v0.1.0](https://github.com/zksecurity/zk-skills), our open-source (MIT-licensed) collection of ZK security skills.
The first version ships **circom-auditor**, a specialized methodology for finding vulnerabilities in Circom projects, compatible with both Claude Code and Codex, as well as runtimes that share their skill formats, such as Cursor.

> [!NOTE] Where these skills fit
>
> Skills are a first line of defense and a pre-audit check.
> They do not replace a deep manual security review, a thorough AI-auditor run, or formal verification.
> They complement them as the first step of the security lifecycle: run them early and often, and fix the bugs before a thorough security review.

## What is inside circom-auditor

A skill is a package of instructions and references that a coding agent loads on demand when a task matches it: markdown files describing a workflow, along with helper scripts the agent can run.
Circom-auditor bundles a security review workflow for Circom circuits, hunting for soundness, completeness, and privacy bugs, and a run goes through four stages.

**Scoping.** A bundled Python script resolves the `.circom` files in scope, builds the include graph, and collects local project docs.
Vendored libraries like [circomlib](https://github.com/iden3/circomlib) are treated as peripheral context: the audit focuses on your code and flags caller-side misuse of library preconditions.

**Hunting.** The audit is split across 17 subagents, with at most 6 running at once.
They all read the same code, but each attacks it from a different angle:

- 6 agents look at the code for known Circom attack vectors: signal and field issues, range checks, selectors and accumulators, binding (split across two agents), and regex/language patterns. These are the classic footguns we keep running into during audits, many of which we have written up in our [Common Circom Pitfalls](https://blog.zksecurity.xyz/posts/circom-pitfalls-1/) series.
- 6 agents each dig into one class of bugs: unconstrained issues, comparator and limb bounds, field arithmetic and wraparound, booleanity of selectors and muxes, cross-template invariants, and domain binding (nullifiers, replay, public inputs). 
- 2 agents ignore known vectors: one trying to violate every circuit's implicit assumptions, and one does a free adversarial pass with no checklist at all.
- 3 agents hunt at whatever has been unexplored, looking for numerical, binding, and composition bugs that fall between the categories above.

**Judging.** Raw findings are deduplicated and then pushed through four sequential gates: can the attack actually be executed against the constraint system, is the bad witness reachable, can a malicious prover exploit it, and does it cause real harm.
Candidates that survive get one more adversarial triage pass asking a fresh agent whether the bug is really exploitable.

**Reporting.** Confirmed findings are formatted into a report with the root cause, a proposed fix, and a note of which agent detected it.
Anything without a concrete exploitable scenario is demoted to a lead rather than silently dropped.

On runtimes without subagent support, the skill falls back to a local single-agent pass over the same catalogs and judging gates.
A full delegated run typically finishes in well under half an hour, depending on model and scope.

Circom-auditor targets small to medium codebases, roughly under 5k lines of Circom.
For larger projects we recommend pointing it at specific circuits, one entrypoint at a time, so each run keeps enough context.

> [!TIP] Getting the most out of it
>
> Put protocol notes and threat models in `assets/docs/`; the auditor uses them to understand intended semantics.
> Keep previous reports in `assets/findings/` so still-relevant issues are revalidated.
> And since LLM review is non-deterministic, run it more than once on high-risk code: different passes surface different bugs.

## Running it

Installation is a clone and a symlink.
For Claude Code:

```bash
git clone https://github.com/zksecurity/zk-skills.git ~/zk-skills
mkdir -p ~/.claude/skills
ln -sfn ~/zk-skills/skills/circom-auditor ~/.claude/skills/circom-auditor
```

For Codex, symlink the same directory into `~/.agents/skills` (or `~/.codex/skills`, depending on your setup).
Then start your agent inside the project you want audited and ask:

```text
Use $circom-auditor to audit the Circom circuits in this repo.
```

You can also name specific files, force a local single-agent pass with "no subagents", or add `--file-output` to write the report under `assets/findings/`.

![circom-auditor running a delegated audit](https://blog.zksecurity.xyz/posts/circom-auditor/circom-auditor-demo.gif)

## Evaluation

To evaluate the skill we used the vulnerable code from [zkbugs](https://github.com/zksecurity/zkbugs), our dataset of ZK circuit vulnerabilities that we have [written about before](https://blog.zksecurity.xyz/posts/zkbugs-website/).
zkbugs already maintains an [evaluation of Circom security tools](https://bugs.zksecurity.xyz/tools-evaluation) on these bugs: symbolic and formal verifiers (Picus, Ecne, ConsCS, Civer), static analysis (Circomspect), and fuzzing (zkFuzz).
That gave us a baseline to compare against.

We ran circom-auditor on two runtimes: Claude Code with Opus 4.8 and Codex with GPT-5.5.
To keep the comparison honest, we removed all git history so the models could not cheat by reading the fix, disabled web access so they could not look the bugs up online.

The benchmark supports two modes.
**Direct** contains only the vulnerable circuit along with the essential circuits it includes, for all 70 bugs.
**Original** contains the entire codebase in which the bug originally existed.

> [!IMPORTANT] How detection is counted
>
> For the two circom-auditor runs, a bug only counts as detected when the triaged report matches the documented ground-truth bug; a report that flags other issues but misses the actual bug counts as a miss.

Here are the results on direct mode:

![Per-tool results on direct mode: Circom Auditor (Claude) finds 66 of 70 bugs and Circom Auditor (Codex) 64 of 70, while the best classic tool, Ecne, finds 30 of 70 and most others fewer than half that, with many runs erroring or timing out.](https://blog.zksecurity.xyz/posts/circom-auditor/eval-direct.png)

Both runs detect over 90% of the bugs: 66/70 with Claude and 64/70 with Codex.
The best classic tool, Ecne, reaches 30/70, and every classic tool loses a chunk of the benchmark to compilation errors and timeouts before analysis even starts.[1](#fn:timeouts)
Ecne deserves a caveat here: it does not really do bug finding.
It checks whether R1CS signals are uniquely determined and flags the constraints it cannot prove sound, leaving you to work out whether and how any of that is exploitable.
That output is hard to act on by itself, but feeding it to an AI agent as leads to investigate is a combination we expect to work well and to point the agent straight at bugs.
More generally, this matches our experience beyond the benchmark: most of these tools verify one property (usually that signals are properly constrained) on circuits they manage to compile, while an LLM auditor reads the circuit the way a human reviewer does and can also flag semantic issues like missing domain separation or a nullifier that fails to bind to the right action.

Original mode is where things get interesting:

![Per-tool results on original mode: Circom Auditor (Claude) finds 40 of 56 bugs, Circom Auditor (Codex) drops to 14 of 56, and the classic tools mostly collapse, with Picus finding none and most runs erroring or timing out.](https://blog.zksecurity.xyz/posts/circom-auditor/eval-original.png)

The classic tools mostly collapse on whole codebases: Picus detects nothing[2](#fn:picus), Ecne drops to 8/56, and Circomspect's 13/56 comes from generic lint warnings.
Circom-auditor with Claude still detects 40/56 (71%).
The surprise is Codex dropping to 14/56.
The most likely explanation is Codex's smaller context window: in original mode the codebase probably no longer fits, so more of it has to be summarized away or skipped.
Further, the Codex runs finished in less than half the time of the Claude ones in this mode (median 8 versus 19 minutes).

> [!CAUTION] Caveats
>
> zkbugs is public, so these bugs may have leaked into the models' training data despite the removed git history and disabled web access; treat the absolute numbers as an upper bound, and the gap between modes and tools as the more reliable signal.
> Also, LLM audits are non-deterministic and these are single runs per bug: a different pass may find a different subset.
> Finally, classic tools produce machine-checkable verdicts and counterexamples, while an LLM report still needs a human to read it.

## Conclusion

With circom-auditor we want to give Circom developers one more tool for building mature, secure circuits, and auditors a fast pre-audit pass that catches the cheap bugs early.
We are open-sourcing the skills so the community can improve them over time: new attack vectors, better lenses, sharper judging, more benchmarks.
Next on our list are skills for other proof systems and DSLs, such as a halo2-auditor and a plonky3-auditor, along with more generic ZK auditing skills.

By its nature, a skill like this only reaches some of the bugs: it is a methodology written down for an off-the-shelf coding agent, bounded by what that agent can explore in a single run.
[zkao](https://zkao.io/) takes a very different approach: instead of instructions layered on a general-purpose agent, it is a purpose-built harness around the models, and it performs far more systematic and thorough analysis and bug-finding exploration than a skill can.
If you maintain a cryptography or ZK project and any of this sounds interesting, we would love to look at it with you, whether through zkao, the skills, or a manual audit.
Reach out at [zksecurity.xyz/contact](https://zksecurity.xyz/contact).

## Acknowledgements

Part of this work was funded through the Ethereum Security quadratic funding round on Giveth, the largest QF matching pool ever run.
A big shout-out to the donors who led this round: [TheDAO Security Fund](https://x.com/TheDAOfund), [Quantstamp](https://x.com/quantstamp) and [Wintermute](https://x.com/wintermute_t).
You can find all the big donors in the [round results](https://forum.giveth.io/t/ethereum-security-qf-round-results-april-23-may-14-2026/2201).
Thank you for supporting open-source security work in Ethereum.

---

1. 
The classic tools run with a 5-minute per-bug timeout, matching the setup of the [zkbugs tools evaluation](https://bugs.zksecurity.xyz/tools-evaluation). That limit is not what holds them back: it was chosen empirically, and rerunning with a larger timeout did not improve the results. The circom-auditor runs have no such limit: the median run took about 14 minutes (Claude) and 9 minutes (Codex) in direct mode, and about 19 and 8 minutes in original mode.qq3936677670287331zz[zz1337820767766393qq](#fnref:timeouts)

   The classic tools run with a 5-minute per-bug timeout, matching the setup of the [zkbugs tools evaluation](https://bugs.zksecurity.xyz/tools-evaluation). That limit is not what holds them back: it was chosen empirically, and rerunning with a larger timeout did not improve the results. The circom-auditor runs have no such limit: the median run took about 14 minutes (Claude) and 9 minutes (Codex) in direct mode, and about 19 and 8 minutes in original mode.qq3936677670287331zz[zz1337820767766393qq](#fnref:timeouts)
2. 
Here, and throughout the evaluation, we run the [open-source version of Picus](https://github.com/Veridise/Picus). Veridise also maintains a proprietary version, and these results say nothing about how that one would do.qq3936677670287331zz[zz1337820767766393qq](#fnref:picus)

   Here, and throughout the evaluation, we run the [open-source version of Picus](https://github.com/Veridise/Picus). Veridise also maintains a proprietary version, and these results say nothing about how that one would do.qq3936677670287331zz[zz1337820767766393qq](#fnref:picus)

---

This article was published on the [ZK/SEC Quarterly](https://blog.zksecurity.xyz) blog by [ZK Security](https://www.zksecurity.xyz), a leading security firm specialized in zero-knowledge proofs, MPC, FHE, and advanced cryptography. ZK Security has audited some of the most critical ZK systems in production, discovered vulnerabilities in major protocols including Aleo, Solana, and Halo2, and built open-source tools like [Clean](https://github.com/Verified-zkEVM/clean) for formally verified ZK circuits. For more articles, see the [full list of posts](https://blog.zksecurity.xyz/llms.txt).
