CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-RJR4-V43M-PXQ6
9.80.04%

The Sponge That Forgot to Wipe: Breaking Triton VM's STARKs

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 15, 2026·6 min read·8 visits

PoC Available

Executive Summary (TL;DR)

Triton VM failed to include the FRI polynomial and trace height in the transcript hash. This broke the Fiat-Shamir binding, allowing attackers to retroactively choose values that satisfy the verifier's challenges, effectively forging proofs for invalid computations.

A critical soundness vulnerability in Triton VM allows attackers to forge Zero-Knowledge proofs by exploiting a flaw in the Fiat-Shamir transform implementation. By failing to absorb specific polynomial coefficients into the cryptographic sponge before generating challenges, the verifier allows a malicious prover to craft the proof after seeing the 'random' challenges.

The Hook: ZK-VMs and the Holy Grail of Soundness

Zero-Knowledge Virtual Machines (ZK-VMs) are the alchemy of modern cryptography. They promise to let you run a program, produce a tiny cryptographic receipt (the proof), and convince anyone that the computation was correct without revealing the inputs. It's magic, but magic relies on strict rules. In the world of STARKs (Scalable Transparent Arguments of Knowledge), the most sacred rule is Fiat-Shamir.

Imagine a magician (the Prover) asking a volunteer (the Verifier) to pick a card. If the magician forces the volunteer to pick the Ace of Spades, it's not a trick; it's a scam. In non-interactive ZK proofs, we replace the volunteer with a cryptographic hash function (a 'random oracle' or 'sponge'). The Prover dumps their work into the sponge, and the sponge squeezes out random challenges. Because the challenges depend on the work, the Prover can't predict them.

Triton VM, a Rust-based ZK-VM, built a sophisticated sponge using the Tip5 hash function. But in version < 2.0.0, the sponge had a little case of selective amnesia. It forgot to look at the Prover's final homework before handing out the grade. And as any cheater knows, if the teacher hands you the answer key before you turn in the test, you're going to get an A+.

The Flaw: A Sponge With Holes

The vulnerability lies deep within the FRI (Fast Reed-Solomon Interactive Oracle Proof of Proximity) protocol implementation. FRI is the heavy lifting engine that proves a polynomial has a low degree. In a proper implementation, every single coefficient and commitment sent by the Prover must be absorbed into the transcript (the sponge state) before the Verifier generates the next challenge.

Triton VM uses a macro called proof_items! to define what gets absorbed. In the vulnerable versions, two critical items were explicitly set to exclude themselves from the sponge:

  1. FriPolynomial: The coefficients of the final polynomial.
  2. Log2PaddedHeight: The size of the execution trace.

Because these values were not absorbed, the random challenges generated by the sponge did not depend on them. This creates a causality loop break. The Prover can compute the challenges first, and then choose a FriPolynomial that happens to satisfy those specific challenges. It effectively turns the system from "I promise this polynomial is valid" to "I found a polynomial that matches the 3 random points you just asked about."

The Code: One Boolean to Rule Them All

The fix is embarrassingly simple, which highlights just how fragile ZK implementations can be. The vulnerability wasn't a buffer overflow or a complex logic error; it was a configuration flag in a Rust macro.

In triton-vm/src/proof_item.rs, the proof_items! macro defines how different parts of the proof interact with the Fiat-Shamir sponge. Look at the diff below. The boolean value indicates whether the item is included in the Fiat-Shamir heuristic (hashed).

Vulnerable Code:

// The 'false' here means: "Don't add this to the hash state"
Log2PaddedHeight(u32) => false, try_into_log2_padded_height,
FriPolynomial(Polynomial<'static, XFieldElement>) => false, try_into_fri_polynomial,

Patched Code (Commit 3a045d636...):

// The 'true' binds the prover to these values BEFORE challenges are issued
Log2PaddedHeight(u32) => true, try_into_log2_padded_height,
FriPolynomial(Polynomial<'static, XFieldElement>) => true, try_into_fri_polynomial,

By flipping false to true, the developers ensured that these values alter the sponge state. If a malicious prover tries to change the polynomial later, the sponge state would be different, resulting in different challenges, invalidating their forged solution.

The Exploit: Painting the Target Around the Arrow

To exploit this, we don't need to break encryption. We just need to abuse the order of operations. Here is how a malicious Prover forges a proof for an invalid state transition (e.g., minting 1,000,000 tokens out of thin air):

  1. Start the Proof: Run the standard proving process, generating the execution trace and committing to the columns.
  2. Reach the FRI Phase: Proceed until the final round of FRI folding. At this point, the Verifier (the code) is about to ask for the FriPolynomial.
  3. Peek at the Future: Since the FriPolynomial isn't hashed, the sponge state depends only on previous items. We can locally calculate exactly what indices (challenges) the verifier will query.
  4. Solve for X: Now that we know the verifier will check indices $i_1, i_2, ... i_k$, we construct a polynomial $P(x)$ such that $P(i_n)$ matches the expected values for a valid proof, but $P(x)$ itself is actually high-degree (invalid). Since the verifier only checks the specific points and didn't bind us to the whole polynomial beforehand, the check passes.
  5. Submit the Forgery: We bundle our malicious polynomial into the proof. The verifier hashes the transcript (missing our polynomial), generates the challenges (which we predicted), checks our polynomial (which we rigged), and returns true.

The Impact: Cryptographic Nihilism

This is a soundness error. In ZK terms, soundness is the guarantee that false statements cannot be proven. With this vulnerability, that guarantee evaporates. If Triton VM is used as the validity proof for a blockchain rollup, an attacker could submit a proof that validates an invalid block—stealing funds, corrupting state, or censoring transactions.

Because the exploit is algorithmic, it is 100% reliable. There is no race condition, no heap grooming, and no luck involved. If you are running a version prior to 2.0.0, any proof you verify is essentially worthless against a sophisticated adversary. The severity is effectively maximum for the context of a ZK system.

The Fix: Update and Verify

The Triton VM team released version 2.0.0 to address this. The patch not only flips the inclusion flags to true but also increments the protocol version number, effectively invalidating all old proofs (since they were generated with a broken Fiat-Shamir transform).

If you are using triton-vm, update your Cargo.toml immediately:

[dependencies]
triton-vm = "2.0.0"

Additionally, the patch introduced sanity checks for log2_padded_height to prevent integer overflows, closing the door on a potential Denial of Service vector where a prover could claim an impossibly large execution trace.

Official Patches

Triton VMCommit fixing the Fiat-Shamir soundness issue

Fix Analysis (1)

Technical Appendix

CVSS Score
9.8/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
EPSS Probability
0.04%
Top 100% most exploited

Affected Systems

Triton VM < 2.0.0Systems relying on Triton VM for STARK verificationRust applications using the `triton-vm` crate

Affected Versions Detail

Product
Affected Versions
Fixed Version
Triton VM
TritonVM
< 2.0.02.0.0
AttributeDetail
CWECWE-345: Insufficient Verification of Data Authenticity
Attack VectorNetwork (Proof Submission)
ImpactProof Forgery / Integrity Compromise
CVSS v3.19.8 (Critical)
Affected ComponentFiat-Shamir Transform (FRI Protocol)
Patch Commit3a045d636e97bb2eb628671db0001aa665c19dd8

MITRE ATT&CK Mapping

T1587Develop Capabilities
Resource Development
T1496Resource Hijacking
Impact
CWE-345
Insufficient Verification of Data Authenticity

Known Exploits & Detection

Research PaperThe Lie in the Sponge: Breaking Triton VM's STARKs

Vulnerability Timeline

Patch committed to main branch
2026-01-19
Triton VM v2.0.0 released
2026-01-19
Advisory GHSA-RJR4-V43M-PXQ6 published
2026-01-22

References & Sources

  • [1]GitHub Advisory GHSA-rjr4-v43m-pxq6

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.