Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain
-
AccessObtain prover status (allowlist today, stake under whitepaper model)
-
DeliveryTake an already-approved block + public validator approval data
-
ExploitBuild valid agg_final proof with extra burn message in unchecked tail
-
ExecutionSubmit proof to RollupV1.verifyRollup()
-
PersistContract parses forged burn as legitimate
-
ImpactUSDC transferred from rollup contract to attacker
Vulnerability Assessment
| Weakness |
CWE
ASVS 5.0
V4 - API and Web Service Acceptance of extraneous untrusted data
|
| Exploitation Conditions | Exploitation requires the attacker to be an authorized prover for the Payy rollup. On the current deployment, RollupV1.verifyRollup() is restricted to an existing allowlisted prover, so a public caller cannot submit the malicious proof - this is the primary limiting factor today. The attacker must also possess the ability to construct a valid agg_final proof for an already-approved rollup block and inject an extra burn message into the unchecked tail of the public messages[1000] array, which demands specialized zk-circuit knowledge. The condition broadens to effectively unauthenticated only under the permissionless prover model in the Payy whitepaper (§3.3.2 stake-to-join, §3.3.1 fallback submission by other nodes), where any staked party can register as a prover. Only affects Payy versions prior to 1.3.0. |
| Impact | This is a genuine, high-severity soundness flaw in a zk-rollup proof system, but its real-world exploitability is heavily gated. The vendor CVSS 4.0 score of 8.7 (VI:H, integrity-only) reflects that a successful attack lets a malicious prover steal USDC directly from the RollupV1 contract - a direct financial-loss/integrity impact, not confidentiality (VC:N) or availability (VA:N). However, the vendor's PR:N (unauthenticated) is misleading for the CURRENT deployment: the description explicitly states verifyRollup() is restricted to an allowlisted prover, so a fresh public caller cannot submit the invalid proof today - that is effectively PR:H right now. PR:N only becomes realistic under the permissionless prover model described in the Payy whitepaper (stake-to-join), which is a future/design condition, not the present state. Verify deployment mode with the vendor before treating this as unauthenticated. No EPSS score, no CISA KEV listing, and no public exploit code are provided - exploitation status is 'no public exploit identified at time of analysis.' Realistic priority is elevated for anyone running or integrating Payy (fund theft, patched), but the combination of prover-allowlist gating, the specialized zk-circuit knowledge needed to craft a malicious agg_final proof, and the tiny deployment footprint means this is a targeted, high-skill issue rather than a mass-exploitation threat. |
| Exploit ScenarioDerived | An entity that is (or becomes) a registered/allowlisted Payy prover takes an already-approved rollup block and its public validator approval data, then builds a valid agg_final proof while appending an extra burn message into the unchecked tail of the public messages array. When RollupV1.verifyRollup() parses that public input, it treats the injected burn as legitimate and transfers USDC from the rollup contract to the attacker's address. No public exploit code was identified at time of analysis; exploitation requires prover status and deep zk-circuit knowledge. |
Get an e-mail when this CVE is exploited, patched or re-scored. Free account.
Alert meAnalysisAIv1 – Sep 28, 2026
Circuit soundness failure in Payy (polybase/payy) prior to 1.3.0 lets an authorized rollup prover smuggle an extra burn message into the public messages[1000] array accepted by RollupV1.verifyRollup(), causing the rollup contract to transfer USDC from the contract to an attacker-controlled recipient. The attacker must be a registered prover with the ability to construct a valid agg_final proof for an already-approved rollup block and to manipulate the unconstrained tail of the public input array, so the assessed vector is authenticated (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N, integrity-only impact with no confidentiality or availability loss). Exploitability today is further limited because verifyRollup() is restricted to the existing allowlisted prover, but the flaw becomes effectively unauthenticated under the permissionless prover model in the Payy whitepaper (Section 3.3.2 stake-to-join and Section 3.3.1 fallback submission by other nodes). No public exploit code had been identified at time of analysis, and the vendor-released patch is version 1.3.0.
RemediationAI
Upgrade to the vendor-released patch, Payy 1.3.0, which constrains the unused tail of the public messages[1000] array so the public statement is fully derived from the verified inner proofs (advisory: https://github.com/polybase/payy/security/advisories/GHSA-fhxc-63vg-9gwr). Until the upgrade is deployed, keep the verifyRollup() allowlist strictly enforced and do not enable stake-to-join or fallback proof submission as described in Payy whitepaper Sections 3.3.2 and 3.3.1, since that converts this authenticated issue into an effectively permissionless one; the trade-off is reduced liveness and decentralization, but the allowlist is the only barrier preventing a registered prover from draining USDC. Additionally, audit and rotate the current allowlisted prover keys, monitor RollupV1 burn events and USDC transfers out of the rollup contract for unexpected recipients, and consider adding an application-layer sanity check that rejects public inputs whose post-message tail is non-zero as a defense-in-depth measure, accepting that such a check is redundant once the circuit itself is fixed and must not be treated as a substitute for the 1.3.0 upgrade.
Affected VersionsENISA
Affected Packages
Source: OSV (Open Source Vulnerabilities)
Affects your stack
Affects 1 package in euvd
Checking this CVE against your own stacks and servers is part of the Basic plan and up.
Technical ContextAI · show details
Payy is an Ethereum L2 zk-rollup focused on privacy-preserving, regulatory-compliant transactions; its proving pipeline aggregates inner proofs in a circuit called agg_agg and finalizes them in agg_final before the on-chain verifier RollupV1.verifyRollup() consumes the resulting public inputs. The agg_agg circuit copies the compacted message stream produced by the verified inner proofs into a fixed-size public array declared as messages: [Field; 1000], but it constrains only the populated prefix and never asserts that the unused tail elements are zero. That missing constraint is a proof-system soundness failure: the prover can satisfy the circuit and publish an arbitrary field element in the tail while still presenting a proof whose statement appears to be derived entirely from the verified inner proofs. RollupV1.verifyRollup() then decodes the public messages array as ordinary rollup operations, so a crafted tail element that parses as a burn instruction is executed by the rollup contract as a genuine burn, moving USDC out of the contract. The root-cause class maps to CWE-349, Acceptance of Extraneous Untrusted Data With Trusted Data, because attacker-chosen data is concatenated into a structure the verifier treats as fully authenticated by the proof. The CPE cpe:2.3:a:polybase:payy:*:*:*:*:*:*:*:* covers all Payy releases before 1.3.0.
Know when Payy gets its next vulnerability
- Watch products and get an email when something new is published
- Check this CVE against your own stack and servers
- Exploit and PoC references, threat intelligence from 22 sources
No credit card · 7-day full trial
Severity by source
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N
Requires registered/staked prover status so PR:L not PR:N; the injected-burn logic is deterministic (AC:L); impact is unauthorized fund transfer (I:H) with no confidentiality or availability effect.
Primary rating from Vendor (GitHub_M).
CVSS VectorVendor: GitHub_M
Lifecycle Timeline
2DescriptionCVE.org
Payy is an Ethereum L2 zk-rollup for privacy preserving and regulatory compliant transactions. Prior to version 1.3.0, agg_agg forwards the compacted message stream from its inner proofs into a public messages: [Field; 1000] array, but it never checks that the unused tail of the outer array is zero. A registered prover can build a valid agg_final proof for an approved rollup block while inserting an extra burn message after the real messages. RollupV1.verifyRollup() then parses that public input as a normal burn and transfers USDC from the rollup contract to the attacker. This is a severe circuit soundness failure: the proof system accepts a public statement whose messages array is not fully derived from the verified inner proofs. On the current deployment, verifyRollup() is restricted to the existing allowlisted prover, so a fresh public caller cannot submit the invalid proof directly. That gate limits who can reach L1 today; it does not make the circuit statement sound. The issue becomes permissionless under the prover model described in the Payy whitepaper. Section 3.3.2 states: "To join as a prover, the prover is required to submit a small stake", and Section 3.3.1 states that if a prover fails to submit, "other nodes can submit the block proof instead." In that model, an attacker only needs to become a registered prover and use public validator approval data for an already approved block. This issue has been patched in version 1.3.0.
Technical POC Analysis
CWE-349 (Acceptance of Extraneous Untrusted Data With Trusted Data) implemented as a circuit soundness failure in the Noir recursive aggregate circuit payy/noir/aggagg/src/main.nr (loop at lines 53-7…
Full technical POC analysis - root cause, step-by-step exploitation and patch breakdown - is part of the Pro and Business plans.
Executive ViewAI
Payy rollup contracts prior to 1.3.0 contain a circuit soundness flaw that allows an authorized prover to divert USDC held by the rollup contract to an attacker-controlled recipient, creating a material integrity and financial risk for any deployment relying on RollupV1.verifyRollup(). Because exploitation requires a registered or allowlisted prover today, immediate exposure is limited, but the planned permissionless prover model would broaden the attack surface and make the issue far more dangerous without a vendor patch. Leadership should prioritize determining whether affected Payy versions are in production, tightening prover access, and monitoring for unauthorized USDC outflows.
No vendor-released patch identified at time of analysis; interim mitigations include restricting RollupV1.verifyRollup() to a tightly controlled, audited allowlist of provers, implementing off-chain/on-chain validation that rejects public input arrays with unexpected tail elements or extra burn messages, adding real-time monitoring and alerting for anomalous USDC transfers and burn events, applying emergency pause/circuit-breaker or transfer timelocks/multisig controls, reducing TVL exposure, and engaging Payy for a patched release.
Threat Intelligence Overview
How this decision was reached
The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.
EUVD-2026-88359
NVD
CVE.org
EPSS
Vulnrichment
GitHub
Exploit-DB