Apr 17, 2026·6 min read·6 visits
Plonky3's `p3-symmetric` crate is vulnerable to cryptographic hash collisions when using `PaddingFreeSponge` with variable-length inputs due to missing domain separation and padding.
The `p3-symmetric` crate in the Plonky3 library implements sponge-based hash functions using cryptographic permutations. Prior to the patch, the library provided a `PaddingFreeSponge` implementation that utilized an overwrite-mode sponge construction without mandatory padding. This construction is not collision-resistant for variable-length inputs, allowing attackers to generate identical internal states for messages of different lengths.
The p3-symmetric crate in the Plonky3 ecosystem implements sponge-based hash functions. These cryptographic primitives absorb input data into an internal state and subsequently squeeze out a fixed-length digest. The library previously relied on a PaddingFreeSponge implementation for various hashing operations.
The PaddingFreeSponge utilizes an overwrite-mode construction without mandatory padding. This design violates the injective encoding requirement necessary for securely hashing variable-length inputs. The vulnerability exists because the sponge fails to properly isolate the internal permutation state when processing inputs that do not align perfectly with the block size.
This lack of domain separation results in cryptographic hash collisions. Systems utilizing this specific sponge implementation for variable-length inputs, such as execution traces in zero-knowledge proof protocols, are susceptible to proof forgery or state manipulation. The fix introduces new sponge variants that enforce strict padding rules to guarantee collision resistance.
The vulnerability originates in the state update mechanism of the overwrite-mode sponge. During the absorption phase, input elements sequentially overwrite the "rate" portion of the internal state. Once the rate portion is filled, the sponge applies a cryptographic permutation to the entire state before accepting further input.
A critical failure occurs when the input length is not an exact multiple of the rate. In this scenario, the final absorption step only overwrites a prefix of the rate portion. The remaining slots in the rate array retain the values produced by the preceding permutation call. The sponge does not clear or separate these residual values before applying the final permutation.
This behavior provides a deterministic mathematical pathway for generating a collision. An attacker can analyze the internal state of a base message of length k. By creating a second message of length k+m, where the appended m elements exactly match the residual state values of the base message, the attacker forces the sponge to recreate the identical internal state.
The vulnerability was addressed in commit 5c1dc1d64c0516a8911bbf3ea40f173c21d6ae47 by Thomas Coratger. The maintainers retained the PaddingFreeSponge for performance-critical, fixed-length operations but introduced Pad10Sponge and MultiField32Pad10Sponge for variable-length inputs. These new structures implement a robust two-case 10-padding scheme to enforce domain separation.
In the first case, the code handles inputs that end mid-block. The patch inserts a sentinel value, generated via a derangement of zero, immediately after the final input element. The algorithm then explicitly zeroes out the remaining slots in the rate portion. This modification clears the residual state from previous permutations, eliminating the primary collision vector.
In the second case, the code handles inputs that perfectly align with the rate boundary. The patch modifies the first element of the "capacity" portion of the state using a mathematical derangement, such as mapping x to x + 1. Because the capacity is not normally overwritten by input data, this mutation guarantees that a full block produces a distinct state from any padded partial block.
// Conceptual representation of the Case 1 Padding fix
if input_len % RATE != 0 {
// Vulnerable: state[input_len..RATE] retains old values
// Patched: Append sentinel and zero remaining slots
state[input_len] = sentinel_value;
for i in (input_len + 1)..RATE {
state[i] = 0;
}
}Exploiting this vulnerability requires specific conditions within the targeted cryptographic protocol. The attacker must interact with a system that uses PaddingFreeSponge to hash variable-length data structures. Furthermore, the attacker must possess the ability to manipulate the length and content of the input data submitted to the hashing function.
The attack begins with the selection of a valid baseline message. The attacker calculates the internal permutation state of the sponge at the exact point where the baseline message absorption concludes. The attacker specifically targets the residual values residing in the unfilled slots of the rate portion.
The attacker crafts a colliding payload by appending these exact residual values to the baseline message. When the vulnerable protocol processes this extended message, the sponge absorbs the appended values into the rate portion. Because these values are identical to the residual state of the shorter message, the sponge arrives at the exact same state before the final squeeze operation.
In zero-knowledge proof systems, this methodology allows for severe manipulation. An attacker can construct a fraudulent execution trace that hashes to the same commitment as a valid trace. This collision bypasses the cryptographic integrity checks, enabling the submission of forged proofs.
The collision vulnerability poses a direct threat to the integrity of cryptographic protocols built on the Plonky3 framework. Zero-knowledge proof systems rely heavily on collision-resistant hash functions to secure Fiat-Shamir heuristics and Merkle tree commitments. A breakdown in collision resistance allows an attacker to alter the underlying data without changing the cryptographic proofs.
The impact is strictly bounded by the application's implementation details. Systems that utilize PaddingFreeSponge exclusively for hashing fixed-length data arrays are mathematically immune to this specific attack. In a fixed-length context, an attacker cannot append the necessary elements to recreate the residual state.
The assigned CVSS score ranges from 2.9 to 4.0, reflecting a Low to Medium severity. This rating accounts for the prerequisite that the vulnerable implementation must be exposed to variable-length, user-controlled inputs. While the cryptographic flaw is fundamental, the exploitation surface is limited to specific architectural designs within the consumer applications.
The primary remediation step is upgrading the Plonky3 library to incorporate commit 5c1dc1d64c0516a8911bbf3ea40f173c21d6ae47. Development teams must update their dependency manifests to pull the patched version of the p3-symmetric crate. This update provides access to the newly implemented, collision-resistant sponge variants.
Following the update, developers must conduct a comprehensive audit of their codebase. All instantiations of PaddingFreeSponge that process variable-length data or user-controlled lists must be replaced. Teams should transition these implementations to use either Pad10Sponge or MultiField32Pad10Sponge, depending on the specific field requirements of the application.
If architectural constraints mandate the continued use of PaddingFreeSponge for performance optimization, developers must implement strict validation controls. The application must enforce rigid, immutable input lengths before the data reaches the hashing function. These constraints should be documented clearly in the protocol specifications to prevent future regressions.
CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
p3-symmetric Plonky3 | < Commit 5c1dc1d6 | - |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-327 |
| Attack Vector | Context-Dependent |
| CVSS Score | 4.0 |
| Impact | Cryptographic Hash Collision |
| Exploit Status | Theoretical/PoC |
| KEV Status | Not Listed |
Use of a Broken or Risky Cryptographic Algorithm