Finding
Severity: Critical
Confirmed against baseline commit d4277510d. The baseline tracked publication only per E3 and did not consume a canonical proof nullifier, so the same valid decryption proof could be reused in another compatible E3 context.
C-03 — Decryption proofs are replayable across unrelated E3 contexts
Affected code: contracts/interfaces/IDecryptionVerifier.sol:8-64,
contracts/verifiers/bfv/BfvDecryptionVerifier.sol:34-39,95-154,
contracts/Interfold.sol:443-459
BfvDecryptionVerifier.verify checks the recursive VK hashes, committee hash,
and plaintext coefficients. It explicitly discards e3Id, committeeRoot,
sortedNodes, ciphertextOutputHash, and committeePublicKey. It also has no
chain ID or verifier-deployment domain input. This contradicts the interface's
claim that the proof is bound to the full on-chain context.
A proof of plaintext P for ciphertext/key/E3 A is accepted for E3 B whenever B
supplies the same committee hash and claimed plaintext hash—even if the E3 ID,
root, nodes argument, ciphertext, and key are different. Cross-chain or
cross-deployment replay is also possible when verifier anchors and committee
hash match.
Proof of concept: AUD-C03 invokes the same proof against two calls with
different E3 IDs, roots, nodes, ciphertext hashes, and public keys; both return
true.
Recommendation: Add a domain/context commitment to the decryption circuit's
public inputs. A single canonical commitment may bind
(block.chainid, address(verifier or Interfold), e3Id, committeeRoot, committeeHash, ciphertextOutputHash, committeePublicKey, plaintextOutputHash, circuit/version domain).
The wrapper must recompute and compare it. Ensure the value is actually
constrained inside the recursive proof chain, not merely appended by an
untrusted aggregator. Add negative tests changing each field independently and
cross-chain/cross-deployment replay vectors.
Required remediation
Consume a canonical decryption-proof nullifier derived from its public inputs and reject cross-E3 proof reuse, with dedicated replay regressions.
The dedicated fixing commit and remediation PR will be linked in a follow-up comment.
Finding
Severity: Critical
Confirmed against baseline commit
d4277510d. The baseline tracked publication only per E3 and did not consume a canonical proof nullifier, so the same valid decryption proof could be reused in another compatible E3 context.C-03 — Decryption proofs are replayable across unrelated E3 contexts
Affected code:
contracts/interfaces/IDecryptionVerifier.sol:8-64,contracts/verifiers/bfv/BfvDecryptionVerifier.sol:34-39,95-154,contracts/Interfold.sol:443-459BfvDecryptionVerifier.verifychecks the recursive VK hashes, committee hash,and plaintext coefficients. It explicitly discards
e3Id,committeeRoot,sortedNodes,ciphertextOutputHash, andcommitteePublicKey. It also has nochain ID or verifier-deployment domain input. This contradicts the interface's
claim that the proof is bound to the full on-chain context.
A proof of plaintext
Pfor ciphertext/key/E3 A is accepted for E3 B whenever Bsupplies the same committee hash and claimed plaintext hash—even if the E3 ID,
root, nodes argument, ciphertext, and key are different. Cross-chain or
cross-deployment replay is also possible when verifier anchors and committee
hash match.
Proof of concept:
AUD-C03invokes the same proof against two calls withdifferent E3 IDs, roots, nodes, ciphertext hashes, and public keys; both return
true.
Recommendation: Add a domain/context commitment to the decryption circuit's
public inputs. A single canonical commitment may bind
(block.chainid, address(verifier or Interfold), e3Id, committeeRoot, committeeHash, ciphertextOutputHash, committeePublicKey, plaintextOutputHash, circuit/version domain).The wrapper must recompute and compare it. Ensure the value is actually
constrained inside the recursive proof chain, not merely appended by an
untrusted aggregator. Add negative tests changing each field independently and
cross-chain/cross-deployment replay vectors.
Required remediation
Consume a canonical decryption-proof nullifier derived from its public inputs and reject cross-E3 proof reuse, with dedicated replay regressions.
The dedicated fixing commit and remediation PR will be linked in a follow-up comment.