VYPR
High severity8.9GHSA Advisory· Published May 21, 2026· Updated May 21, 2026

Plonky3 MultiField32Challenger: transcript malleability and challenge entropy loss

CVE-2026-46654

Description

Impact

  • Key: challenger/src/multi_field_challenger.rs | MultiField32Challenger::duplexing | transcript_malleability
  • Affected files: challenger/src/multi_field_challenger.rs, field/src/helpers.rs
  • Violated invariant: The Fiat-Shamir sponge must bind challenges to the exact sequence of observed field elements. Specifically: (1) absorption must be injective — distinct observation streams must produce distinct sponge states, (2) squeezing must be injective — distinct PF rate cells must yield distinct F challenge sequences, and (3) all bits of each absorbed PF element must influence the sponge state.
  • Exploit scenario: An attacker controlling prover-side observations can craft distinct transcripts that produce identical challenges, breaking the binding property of Fiat-Shamir. Three independent attack vectors exist:
  1. Partial-chunk aliasing (absorb): duplexing() packs input_buffer.chunks(num_f_elms) via reduce_32 (base 2^32) with no length marker and no zeroing of unused rate slots. Observing [x] followed by a sample yields the same sponge state as [x, 0, ..., 0] (padded to num_f_elms) followed by a sample, since reduce_32 treats missing high limbs identically to explicit zeros. The attacker can extend or truncate the tail of any observation batch without changing future challenges.
  1. Non-injective squeeze (squeeze): split_32 decomposes each PF rate cell into base-2^64 digits and maps each through TF::from_u64, which reduces mod F::ORDER (~2^31). Two distinct PF values whose base-2^64 digits differ only in their upper 33 bits produce identical F challenge sequences. This weakens the entropy of sampled challenges and can enable selective forgery when the attacker can influence the sponge state pre-squeeze.
  1. High-bit truncation (observe Hash/MerkleCap): num_f_elms = PF::bits() / 64 computes the number of F limbs per PF element. For BN254 (254-bit field), this yields 3 limbs covering 192 bits — the top 62 bits of every digest word are silently discarded. An attacker can find two distinct BN254 hash digests that differ only in bits 192–253 and observe them interchangeably without affecting challenges.
  • Evidence: In duplexing(), the absorb path (reduce_32 with base 2^32) and the squeeze path (split_32 with base 2^64) use incompatible radices with no length domain separation. reduce_32 is a plain Horner fold acc * 2^32 + digit with no padding or tag, so trailing zeros are free. split_32 extracts u64 digits and casts each via TF::from_u64, which performs modular reduction, collapsing the top bits. The limb count PF::bits() / 64 is a floor division that silently drops all bits beyond 64 * num_f_elms for fields whose bit-width is not a multiple of 64.

Patches

Included in v0.4.3 and v0.5.3

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Plonky3's MultiField32Challenger has three design flaws allowing transcript malleability, enabling attackers to forge proofs by manipulating observations to produce duplicate challenges.

CVE-2026-46654 describes a set of high-severity vulnerabilities in Plonky3's MultiField32Challenger, a component implementing the Fiat-Shamir transform for proof systems. The core issue is a violation of the invariant that the sponge must bind challenges to the exact sequence of observed field elements. Three independent flaws exist in the duplexing() function, which handles absorption and squeezing, and in the handling of hash digests for proofs like Merkle caps [1][2].

Attack

Vectors The first vector, *partial-chunk aliasing*, occurs during absorption: duplexing() processes input chunks via reduce_32 without marking length or zeroing unused rate slots, so observing [x] followed by a sample produces the same sponge state as [x, 0, ..., 0]. The second, *non-injective squeeze*, results from split_32 mapping PF rate cells to base‑2^64 digits and then reducing modulo F::ORDER (~2^31), meaning two distinct PF values whose digits differ only in the upper 33 bits yield identical challenge sequences. The third, *high-bit truncation*, applies when absorbing hash digests or Merkle cap data: num_f_elms = PF::bits() / 64 computes the number of limbs per PF element, and for BN254 (254-bit field) this truncates the top 62 bits of every digest word [1][2].

Impact

An attacker who can control prover-side observations can exploit any of these vectors to craft distinct transcripts that produce identical challenges. This breaks the binding property of the Fiat-Shamir heuristic, enabling selective forgery of proofs without detection. The vulnerability weakens the entropy of sampled challenges and allows transcript malleability, potentially leading to complete compromise of proof soundness [1][2].

Mitigation

Patches are available in version 0.4.3 (for the 0.4.x line) and 0.5.3 (for 0.5.x). Users should upgrade immediately. No workarounds have been published, and the flaw is not yet listed in CISA's Known Exploited Vulnerabilities catalog [1].

AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

1

Patches

0

No patches discovered yet.

Vulnerability mechanics

AI mechanics synthesis has not run for this CVE yet.

References

2

News mentions

0

No linked articles in our index yet.