Inside Ziren's security collaboration with Consensys Diligence

Share on

Seven months of responsible disclosure, an upstream LLVM fix, an agent-driven mining sweep, and two hardened releases - a record of what security work looks like when it happens in the open.

In mid-December 2025, a message reached the Ziren team through the Ethereum Foundation. Consensys Diligence, together with researchers at TU Wien, had pointed their fuzzing infrastructure at Ziren - and it had already found something.

The fuzzer in question, Arguzz, was built to test zero-knowledge virtual machines by generating equivalent programs and flagging any divergence in how the VM handles them. It originally targeted RISC-V systems. A Master's student at TU Wien, Mathias Möller, was building a MIPS backend for it to validate that the approach generalizes - and Ziren, a zkVM built on MIPS32, was the natural target. The prototype found a completeness bug before the backend was even finished.

What began as a single disclosure channel became seven months of continuous collaboration between the Ziren team, Consensys Diligence, TU Wien, and the Ethereum Foundation: five bugs found by fuzzing, each reproduced, fixed, and independently re-verified; one fix landed upstream in LLVM itself; a formal determinism-checking backend contributed to the repository; a full agent-driven vulnerability mining sweep triaged and closed; and two hardened releases shipped. This article is the record of that work.

Why fuzz a zkVM at all

A zkVM has two failure modes that matter more than crashes.

A completeness bug means a correct program fails to execute or prove - the system rejects something it should accept. Annoying, visible, and usually caught quickly in practice.

A soundness bug is the dangerous one: a malicious prover constructs a valid-looking proof of an execution that never happened, or of a result that is simply wrong. Soundness bugs are silent. Nothing crashes. The proof verifies. For any system where value or state depends on those proofs, soundness is the entire point.

Fuzzing attacks both. Arguzz and its predecessor Circuzz (published at CCS 2025; the Arguzz paper appears at USENIX Security 2026) generate circuits or programs, derive semantically equivalent variants through metamorphic transformations, run them through the full pipeline - compile, execute, prove, verify - and flag any divergence between the two. If equivalent inputs produce different behavior at any stage, the pipeline has a bug. Across eight ZK systems including Circom, Jolt, gnark, Noir, and RISC Zero, the Consensys and TU Wien fuzzers have found 59 major bugs to date, 27 of them critical soundness issues. Ziren joined that program in December.

Bug one: the compiler was the culprit

The first report arrived within a day of the disclosure channel opening. Custom inline assembly using the MIPS div instruction caused the Ziren executor to panic with an unsupported-instruction error. The failing pattern was oddly specific: any two equal inputs triggered it, as did dividing by -1.

The execution trace told the story. Both input operands were being allocated to the same register, which turned the compiler's subsequent overflow-check branches into comparisons of a register against itself - and execution fell through to a BREAK trap that should never have been reachable.

Ziren's executor was not the problem. The bug lived in LLVM's MIPS assembly parser - specifically in how MipsAsmParser::expandDivRem handled register allocation for the expanded division sequence. The Ziren team traced it, filed it upstream, and followed the fix through review (llvm/llvm-project#172967, with the remaining efficiency-related issue tracked in #174909). The LLVM patch merged on December 23. A new Ziren toolchain release (20260108) shipped the fix in early January, and TU Wien confirmed the reproduction case was resolved.

One bug in, and the collaboration had already improved a compiler used far beyond Ziren.

Bug two: what does the spec actually say

In late February the fuzzer flagged div again - this time for overflow behavior. Dividing i32::MIN by -1 caused the executor to panic with an arithmetic overflow error. The MIPS specification is explicit that no arithmetic exception occurs for the div instruction under any circumstances, so a panic is a completeness violation: a program the ISA defines as legal could not be executed or proven.

The discussion that followed is a good example of why these channels matter. Is this LLVM's problem, the executor's, or undefined behavior that nobody owns? The researchers walked the pipeline step by step and isolated it: the panic occurred while the executor interpreted an already-emitted MIPS instruction, so the fix belonged in the executor. The resolution - computing the quotient with wrapping semantics, matching both the MIPS spec and the approach taken by comparable zkVMs - shipped in the next release cycle. The same class of issue had been noted in Veridise's audit of Ziren (V-ZKM-VUL-010, overflowing arithmetic), with this specific div case now covered as well.

Bugs three, four, and five: the soundness findings

In March the reports changed character. The fuzzer stopped finding programs that failed to run and started finding proofs that should not exist.

The first soundness issue involved the teq instruction, commonly emitted to check for division by zero. Its constraints left the rs register insufficiently bound, which allowed a prover to inject an arbitrary value at that point in the trace. The proof-of-concept was blunt: a guest program computing gcd(100, 40) could be "proven" to return 123 - or any other value supplied through an environment variable - and the resulting proof verified. The fix (ProjectZKM/Ziren#474) constrained the immutability of the register and added booleanity and one-hot constraints to related selector columns, closing findings surfaced in parallel by Veridise's Picus tool.

The second, in mid-March, hit the ins instruction. Executing ins a, b, 0, 32 - which should fully overwrite one register with another - produced an out-of-domain evaluation mismatch on the ShiftRight chip, while a modified executor performing a different operation entirely could produce a valid proof. The root cause was a shift amount of 32 exceeding the chip's supported range of 0 to 31. Fixed in ProjectZKM/Ziren#477 by splitting the operation into two staged shifts.

The third, reported on April 1, was in the syscall path: a window existed where a malicious prover could overwrite a syscall's return value after execution but before write-back to the V0 register. The finding was confirmed on both the main branch and the pre-release line, generalized to NOP syscalls, and closed alongside a set of related syscall AIR constraints tracked in ProjectZKM/Ziren#488.

All three fixes, plus the constraint hardening that came out of the parallel Picus analysis, were merged into the pre-release v1.2.5 branch (ProjectZKM/Ziren#459) and then into main. The external fuzzers were re-run against the fixed branch as each issue closed - reported, fixed, and independently re-verified, in every case.

The second wave: agent-driven mining

In June the collaboration changed scale. Diligence ran Vulnerability Mining, its proprietary technique for agentic vulnerability discovery, across the Ziren codebase and shared the full output through minr, its self-service triage platform: candidate findings sorted by priority and exploitability, an experimental root-cause analysis clustering hundreds of raw findings into a much smaller set of underlying causes, and proof-of-concept scaffolding for the issues that mattered most.

Candidate findings from automated mining are not the same thing as confirmed bugs - the point of minr is to separate the two quickly. The Ziren team worked through the queue, and the fixes came fast: the keccak sponge initial-state constraint (ProjectZKM/Ziren#517), followed by a consolidated fix branch closing out the remaining confirmed issues (ProjectZKM/Ziren#519). Within two weeks, every confirmed finding of critical, high, or medium severity had a fix on the branch.

Then the tools checked each other. Arguzz-generated exploits for the mining findings were run against the fix branch: each exploit was rejected and the guest programs ran normally. When Diligence re-assessed the v1.2.6 release against the previous scan, 21 findings were confirmed fixed - and the reassessment caught one newly introduced completeness regression, which entered the same triage-and-fix loop. That is the pipeline working as designed: mining surfaces candidates, triage confirms them, fixes land, fuzzing re-verifies, and reassessment catches drift.

One more detail worth noting: Diligence is coordinating publication of its findings across all the zkVM teams in its program, holding public disclosure until fixes are in everywhere. Ziren's fixes are in. That is what responsible disclosure looks like at ecosystem scale.

What this changed

The concrete output: an upstream LLVM fix, corrected div semantics, three closed soundness issues from fuzzing, a Picus determinism-checking backend in the repository (ProjectZKM/Ziren#442), a full mining sweep triaged with every confirmed critical, high, and medium finding fixed, hardened constraint sets across the SEXT, TEQ, syscall, keccak, and memory paths, and the v1.2.5 and v1.2.6 releases that carry all of it. Every fix is public, every reproduction case is documented, and the external researchers confirmed each resolution independently.

The less concrete output matters as much. Ziren proves real workloads in production contexts, including the bridge infrastructure securing GOAT Network's Bitcoin L2 - which is precisely why this class of bug has to be found by a fuzzer in a disclosure channel rather than by an attacker with a forged proof. The soundness findings above were reported, fixed, and verified in the pre-release cycle, before the systems that depend on them went to mainnet.

Security work in this industry is often invisible until it fails. We think the better model is the one this collaboration demonstrates: external researchers with serious tooling, a direct channel to the engineers who own the code, fast turnarounds, upstream fixes where the root cause lives upstream, tools that cross-validate each other's results, and a public record when the work is done. What started as a bug report is now an ongoing working relationship, and we expect the pipeline described here to keep running against every future release.

Our thanks goes out to Tobias Vogel, tintinweb, and Valentin Wüstholz from the Consensys Diligence team, the researchers at TU Wien, and the Ethereum Foundation (especially Will Corcoran for the initial introduction).

The fuzzers are still running.

ZKM: zkm.io

Consensys Diligence: diligence.security 

Ziren (formerly zkMIPS) is an open-source, simple, stable, and universal zkVM on MIPS32. The fixes described in this article are available from release v1.2.5 onward, with the mining-cycle fixes in v1.2.6 and later. Researchers interested in testing Ziren can reach the team through the ProjectZKM GitHub organization.

More articles
ZKM + GOAT Network: An End-to-End Stack for Bitcoin-scaling
A question that frequently arises is: “What is the relationship between ZKM and GOAT Network?” ZKM built the core proving and execution stack - Ziren (ZKM’s MIPS-based zkVM), the distributed prover, and the verification toolchain - that underpins GOAT Network. GOAT is the first production deployment where Ziren is the default proving engine across the system: proving L2 state transitions, securing the native bridge, and enabling low-latency proof generation for Bitcoin-aligned flows.
Cross-chain Asset Transfer Without a Bridge - Part One
To accomplish cross-chain asset transfer, most of the solutions currently available are based on a bridge, a separate, intermediate entity, which is typically trusted with holding these assets during some period of the transaction. This trust assumption is undesirable since it provides a large opportunity for attack. In this post I will explain that, assuming the existence of a zkRollup, one can implement cross-chain asset transfer without the need for additional trust assumptions (such as a bridge).
Inside Ziren's security collaboration with Consensys Diligence

Seven months of responsible disclosure, an upstream LLVM fix, an agent-driven mining sweep, and two hardened releases - a record of what security work looks like when it happens in the open.

In mid-December 2025, a message reached the Ziren team through the Ethereum Foundation. Consensys Diligence, together with researchers at TU Wien, had pointed their fuzzing infrastructure at Ziren - and it had already found something.

The fuzzer in question, Arguzz, was built to test zero-knowledge virtual machines by generating equivalent programs and flagging any divergence in how the VM handles them. It originally targeted RISC-V systems. A Master's student at TU Wien, Mathias Möller, was building a MIPS backend for it to validate that the approach generalizes - and Ziren, a zkVM built on MIPS32, was the natural target. The prototype found a completeness bug before the backend was even finished.

What began as a single disclosure channel became seven months of continuous collaboration between the Ziren team, Consensys Diligence, TU Wien, and the Ethereum Foundation: five bugs found by fuzzing, each reproduced, fixed, and independently re-verified; one fix landed upstream in LLVM itself; a formal determinism-checking backend contributed to the repository; a full agent-driven vulnerability mining sweep triaged and closed; and two hardened releases shipped. This article is the record of that work.

Why fuzz a zkVM at all

A zkVM has two failure modes that matter more than crashes.

A completeness bug means a correct program fails to execute or prove - the system rejects something it should accept. Annoying, visible, and usually caught quickly in practice.

A soundness bug is the dangerous one: a malicious prover constructs a valid-looking proof of an execution that never happened, or of a result that is simply wrong. Soundness bugs are silent. Nothing crashes. The proof verifies. For any system where value or state depends on those proofs, soundness is the entire point.

Fuzzing attacks both. Arguzz and its predecessor Circuzz (published at CCS 2025; the Arguzz paper appears at USENIX Security 2026) generate circuits or programs, derive semantically equivalent variants through metamorphic transformations, run them through the full pipeline - compile, execute, prove, verify - and flag any divergence between the two. If equivalent inputs produce different behavior at any stage, the pipeline has a bug. Across eight ZK systems including Circom, Jolt, gnark, Noir, and RISC Zero, the Consensys and TU Wien fuzzers have found 59 major bugs to date, 27 of them critical soundness issues. Ziren joined that program in December.

Bug one: the compiler was the culprit

The first report arrived within a day of the disclosure channel opening. Custom inline assembly using the MIPS div instruction caused the Ziren executor to panic with an unsupported-instruction error. The failing pattern was oddly specific: any two equal inputs triggered it, as did dividing by -1.

The execution trace told the story. Both input operands were being allocated to the same register, which turned the compiler's subsequent overflow-check branches into comparisons of a register against itself - and execution fell through to a BREAK trap that should never have been reachable.

Ziren's executor was not the problem. The bug lived in LLVM's MIPS assembly parser - specifically in how MipsAsmParser::expandDivRem handled register allocation for the expanded division sequence. The Ziren team traced it, filed it upstream, and followed the fix through review (llvm/llvm-project#172967, with the remaining efficiency-related issue tracked in #174909). The LLVM patch merged on December 23. A new Ziren toolchain release (20260108) shipped the fix in early January, and TU Wien confirmed the reproduction case was resolved.

One bug in, and the collaboration had already improved a compiler used far beyond Ziren.

Bug two: what does the spec actually say

In late February the fuzzer flagged div again - this time for overflow behavior. Dividing i32::MIN by -1 caused the executor to panic with an arithmetic overflow error. The MIPS specification is explicit that no arithmetic exception occurs for the div instruction under any circumstances, so a panic is a completeness violation: a program the ISA defines as legal could not be executed or proven.

The discussion that followed is a good example of why these channels matter. Is this LLVM's problem, the executor's, or undefined behavior that nobody owns? The researchers walked the pipeline step by step and isolated it: the panic occurred while the executor interpreted an already-emitted MIPS instruction, so the fix belonged in the executor. The resolution - computing the quotient with wrapping semantics, matching both the MIPS spec and the approach taken by comparable zkVMs - shipped in the next release cycle. The same class of issue had been noted in Veridise's audit of Ziren (V-ZKM-VUL-010, overflowing arithmetic), with this specific div case now covered as well.

Bugs three, four, and five: the soundness findings

In March the reports changed character. The fuzzer stopped finding programs that failed to run and started finding proofs that should not exist.

The first soundness issue involved the teq instruction, commonly emitted to check for division by zero. Its constraints left the rs register insufficiently bound, which allowed a prover to inject an arbitrary value at that point in the trace. The proof-of-concept was blunt: a guest program computing gcd(100, 40) could be "proven" to return 123 - or any other value supplied through an environment variable - and the resulting proof verified. The fix (ProjectZKM/Ziren#474) constrained the immutability of the register and added booleanity and one-hot constraints to related selector columns, closing findings surfaced in parallel by Veridise's Picus tool.

The second, in mid-March, hit the ins instruction. Executing ins a, b, 0, 32 - which should fully overwrite one register with another - produced an out-of-domain evaluation mismatch on the ShiftRight chip, while a modified executor performing a different operation entirely could produce a valid proof. The root cause was a shift amount of 32 exceeding the chip's supported range of 0 to 31. Fixed in ProjectZKM/Ziren#477 by splitting the operation into two staged shifts.

The third, reported on April 1, was in the syscall path: a window existed where a malicious prover could overwrite a syscall's return value after execution but before write-back to the V0 register. The finding was confirmed on both the main branch and the pre-release line, generalized to NOP syscalls, and closed alongside a set of related syscall AIR constraints tracked in ProjectZKM/Ziren#488.

All three fixes, plus the constraint hardening that came out of the parallel Picus analysis, were merged into the pre-release v1.2.5 branch (ProjectZKM/Ziren#459) and then into main. The external fuzzers were re-run against the fixed branch as each issue closed - reported, fixed, and independently re-verified, in every case.

The second wave: agent-driven mining

In June the collaboration changed scale. Diligence ran Vulnerability Mining, its proprietary technique for agentic vulnerability discovery, across the Ziren codebase and shared the full output through minr, its self-service triage platform: candidate findings sorted by priority and exploitability, an experimental root-cause analysis clustering hundreds of raw findings into a much smaller set of underlying causes, and proof-of-concept scaffolding for the issues that mattered most.

Candidate findings from automated mining are not the same thing as confirmed bugs - the point of minr is to separate the two quickly. The Ziren team worked through the queue, and the fixes came fast: the keccak sponge initial-state constraint (ProjectZKM/Ziren#517), followed by a consolidated fix branch closing out the remaining confirmed issues (ProjectZKM/Ziren#519). Within two weeks, every confirmed finding of critical, high, or medium severity had a fix on the branch.

Then the tools checked each other. Arguzz-generated exploits for the mining findings were run against the fix branch: each exploit was rejected and the guest programs ran normally. When Diligence re-assessed the v1.2.6 release against the previous scan, 21 findings were confirmed fixed - and the reassessment caught one newly introduced completeness regression, which entered the same triage-and-fix loop. That is the pipeline working as designed: mining surfaces candidates, triage confirms them, fixes land, fuzzing re-verifies, and reassessment catches drift.

One more detail worth noting: Diligence is coordinating publication of its findings across all the zkVM teams in its program, holding public disclosure until fixes are in everywhere. Ziren's fixes are in. That is what responsible disclosure looks like at ecosystem scale.

What this changed

The concrete output: an upstream LLVM fix, corrected div semantics, three closed soundness issues from fuzzing, a Picus determinism-checking backend in the repository (ProjectZKM/Ziren#442), a full mining sweep triaged with every confirmed critical, high, and medium finding fixed, hardened constraint sets across the SEXT, TEQ, syscall, keccak, and memory paths, and the v1.2.5 and v1.2.6 releases that carry all of it. Every fix is public, every reproduction case is documented, and the external researchers confirmed each resolution independently.

The less concrete output matters as much. Ziren proves real workloads in production contexts, including the bridge infrastructure securing GOAT Network's Bitcoin L2 - which is precisely why this class of bug has to be found by a fuzzer in a disclosure channel rather than by an attacker with a forged proof. The soundness findings above were reported, fixed, and verified in the pre-release cycle, before the systems that depend on them went to mainnet.

Security work in this industry is often invisible until it fails. We think the better model is the one this collaboration demonstrates: external researchers with serious tooling, a direct channel to the engineers who own the code, fast turnarounds, upstream fixes where the root cause lives upstream, tools that cross-validate each other's results, and a public record when the work is done. What started as a bug report is now an ongoing working relationship, and we expect the pipeline described here to keep running against every future release.

Our thanks goes out to Tobias Vogel, tintinweb, and Valentin Wüstholz from the Consensys Diligence team, the researchers at TU Wien, and the Ethereum Foundation (especially Will Corcoran for the initial introduction).

The fuzzers are still running.

ZKM: zkm.io

Consensys Diligence: diligence.security 

Ziren (formerly zkMIPS) is an open-source, simple, stable, and universal zkVM on MIPS32. The fixes described in this article are available from release v1.2.5 onward, with the mining-cycle fixes in v1.2.6 and later. Researchers interested in testing Ziren can reach the team through the ProjectZKM GitHub organization.