ZK/SEC Research notes from zkSecurity
All posts
announcement · tools · security

You like Circom but you find it confusing? Introducing Circomscribe

circomscribe

If you've been working in the field of zero-knowledge in the last few years you must have heard of Circom, a tool to write zero-knowledge applications in the form of circuits. Many projects have used Circom, that is the least one could say, as perhaps most ZK projects that have been built as smart contracts directly on Ethereum have been built using Circom; the most infamous project probably being TornadoCash.

While Circom has been great for developers wishing to explore usecases brought by zero-knowledge proofs, it is an extremely low-level tool, and it has proven to be quite hard to use correctly. One could almost say that if you don't understand how circuits (or proof systems) work at a low-level, you're going to run into trouble.

circom program example

As part of auditing ZK applications, zkSecurity has gone through its fair share of Circom circuits audits, and has realized that one of the biggest source of bugs (besides human error) is that developers have little idea of how their code eventually gets transcribed into "constraints" by the Circom compiler. In a way, it is similar to not being able to see the assembly your code compiles to, and as such making wrong assumptions sometimes.

While many more user-friendly and secure zk platforms and tools are making their way in (including our own in-house noname), the ecosystem of today is still very much based on Circom. So what can we do about this?

I say: let's improve everyone's understanding of how their Circom code gets compiled down to constraints! The more we educate developers, the less bugs they will write. To achieve this, we'd like to introduce Circomscribe.

Circomscribe is a tool that shows you what Circom does with your code. Simple as that. Paste your complete circuit in the tool, press a button, and quickly get an idea of what lines of code produce what constraints (if any).

For example, here's the analysis of the Num2Bits template (which converts a value to a list of bits) taken directly from circomlib, the standard library of Circom:

Circomscribe

As you can see, only the lines of code that are highlighted on the left produce constraints. These constraints are "pure" constraints, which is what the compiler produces before actually unrolling the circuit (for example, if a template is used several times) and before any optimizations are performed. So in a sense, this is purely useful to understand the first pass of the compiler, but not useful to see what the actual compiled circuit looks like.

Underneath, Circomscribe is essentially a modified version of the Circom compiler to run in WASM and emit information in a JSON format when compiling. As of now, the Circomscribe tool provides simple features that we hope will be useful to developers and other security engineers. We hope to add more features in the future. If you have any ideas, please let us know!

Keep reading
Latest

The Year Finding and Exploiting Bugs Became Cheap, and What to Do About It

The economics of security have changed. AI has made finding and exploiting bugs cheaper, including in cryptographic and zero-knowledge code, while validation and remediation remain slow. Here is our view of what happened, what comes next, and how teams should change the way they secure their stack to defend against AI-assisted attackers.

Stefanos Chaliasos · September 07, 2026

Variants of KZG: Part V, Multilinear Commitments with Mercury

In this final post of the series, we extend univariate KZG commitments to multilinear polynomials through Mercury. Building on Gemini, we fold half of the variables at once, use polynomial division to bind this large fold to the original commitment and reduce the remaining multilinear evaluations to a batched inner product check. We then walk through the end-to-end opening protocol. We conclude by examining its proof size, prover cost and verifier cost.

Varun Thakore · August 17, 2026

Variants of KZG: Part IV, Multilinear Commitments with Gemini

In this blog post, we extend univariate KZG commitments to multilinear polynomials through Gemini. We introduce recursive partial evaluations, derive the split-and-fold identity and express each fold as a univariate identity that can be checked using KZG openings. We then walk through the end-to-end opening protocol. We conclude by examining its proof size, prover cost, and verifier cost.

Varun Thakore · August 12, 2026
Recommended

Common Circom Pitfalls and How to Dodge Them, Part 1

Programming in Circom comes with its fair share of challenges. After reviewing numerous Circom codebases, we’ve identified certain anti-patterns that occur frequently. In this series, we’ll provide a comprehensive overview of these issues to help you avoid the most common pitfalls. Of course, this won’t be a complete list of every mistake possible (Circom has plenty of ways to trip you up). But the footguns we’ll cover are the ones that tend to catch developers off guard the most.

Marco Besier · June 24, 2025

Introducing clean, a formal verification DSL for ZK circuits in Lean4

We're diving into our new project called **clean**, aimed at creating an embedded DSL and formal verification framework for Zero Knowledge (ZK) circuits using Lean4. Imagine being able to not only define ZK circuits but also formally prove their correctness. Sounds like a game-changer, right? We'll walk you through our process of building a robust library of reusable, verified circuit gadgets, focusing on the importance of soundness and completeness. Plus, you'll get a peek at some cool examples like 8-bit addition and how we're tackling ZKVM design with techniques borrowed from Fibonacci sequences. It's exciting stuff, and if you're curious about how we're paving the way for bug-free ZK circuits, this is a read you won't want to miss!

Giorgio Dell'Immagine · March 27, 2025

Public report of Darkfi circuits and crypto audit

In February 2024, we dived into a security audit of Darkfi's built-in contracts and circuits, putting them under the microscope to ensure everything checks out. Curious to know what we discovered while navigating the public Darkfi repository? Check out our full report for insights and findings.

ZK/SEC · February 27, 2024
More to explore

ZNARKs: SNARKs for The Integers

Hey there! Interested in learning about SNARKs that work beyond finite fields? We’ve been diving into $\mathbb{Z}$NARKs, which are SNARKs tailored for computations involving integers. Our latest post unpacks this intriguing area, showing how we can construct efficient proof systems for integer-based computations. You'll discover nifty tricks like range checks without bit decomposition and mixed field emulation, plus how these techniques can simplify RSA computations. Intrigued by the idea of using randomness for more reliable proofs or exploring an intellectual curiosity like $\mathbb{Q}$-circuits? This post covers it all, including a peek into the future of polynomial commitments. Dive in and explore with us!

Mathias Hall-Andersen · November 11, 2024

zkao: Security That Compounds

Today we're launching zkao, a product by zkSecurity that makes AI security research work the way fuzzing works: not as a one-shot event, but as something you run continuously until coverage compounds.

ZK/SEC · February 07, 2026

Reproducing and Exploiting ZK Circuit Vulnerabilities

Check out our latest blog post where we dive into the world of Zero-Knowledge Proof (ZKP) vulnerabilities, sharing our insights from replicating known ZK circuit weaknesses. We’ve launched a GitHub repo with detailed scripts to help you understand, reproduce, and learn from these vulnerabilities. Discover how this hands-on approach aids in grasping attack vectors, testing fixes, and enriching educational resources. Whether you're a researcher or a developer, this post is packed with info to enhance your knowledge and skills in ZKP security. Plus, find out how you can contribute to expanding this invaluable resource!

Stefanos Chaliasos, Chenyang Yu · August 09, 2024