Skip to content

Dangerous L1 event finality assumptions & Failed transactions not considered

Moderate
noonio published GHSA-qr9f-mpgf-wp25 Jun 17, 2025

Package

hydra-node

Affected versions

0.20.0

Patched versions

None

Description

Summary

Currently Hydra monitors the Cardano L1 for certain events and relies on those events for state progression (ie. incremental commitments). At the moment, Hydra considers those events as finalized as soon as they are recognized by the node participants (ie. as soon as they are made available to the cardano-node that is executing), this is quite dangerous, because it makes such transactions the target of re-org attacks.

Please do not share the following paragraph or any information that could point malicious actors to the idea of deliberately submitting failed txs. There are protocols on mainnet with significant funds that are vulnerable to these attacks (bridges and vending machines), and even more that are vulnerable from a social perspective (many DeFi protocols you can arbitrarily inflate metrics by tricking the offchain metrics into believing there is activity that doesn't exist, which then gets reflected in the UI). Please handle this information sensitively.

Furthermore, the system does not currently consider the fact that failed transactions on the Cardano L1 can indeed appear in blocks. The only cases in which failed txs should appear in blocks is when a party is deliberately submitting it with the knowledge that it will fail and paying the network for the work accordingly. Indeed, pretty much the only practical reason to submit failed transactions to the network is for malicious purposes (because these transactions are so infrequent, many dApps do not handle them correctly).

Details

For re-orgs targeting incremental commits:

  1. deposit transaction that needs to be signed and submitted by the user in order to kick-off the deposit process.
  2. The hydra node must observe this deposit and issue an increment for it within the deposit deadline (set to 3600 seconds by default)
  3. Once a hydra-node observes a deposit transaction it will record the deposit as pending into the local state. There can be many pending deposits, but the new Snapshot will include them one by one.

The issue is that if the deposit tx gets subject to a re-org, the hydra head will desync and completely brick out. An elegant fix to this would be to set the time window in which we expect the hydra-node to be able to issue an increment transaction for a given deposit to start timeToProbabilisticFinality seconds after the deposit has been observed. This means upon observing a deposit, participants will not do anything with said deposit until timeToProbabilisticFinality seconds have passed, at which point they simply reconfirm the presence of the deposit UTxO in the ledger (assuring that it hasn't been subject to a re-org) and proceed normally if it still exists or just remove it from the local state if the deposit no longer exists.

For failed transactions, because Hydra observes the Cardano L1 for transactions relevant to the deposit address it needs to actually verify that the transaction progresses the state of the ledger (UTxO set / accounts). Failed transactions do not progress the ledger state, and as such must be discarded / handled as if they did not occur.

PoC

Re-org attack:

  1. Submit deposit transaction for incremental commit
  2. Hydra nodes observe the deposit and put it into local state to queue it for increment tx
  3. re-org causes deposit tx to no longer be valid on the canonical fork

Failed tx attack:

  1. Submit a deposit transaction with a failed transaction (include a plutus script that fails and forcefully submit it and pay collateral accordingly)
  2. Observe how Hydra handles it

For the failed tx, you should perform the same for any other L1 txs that are observed to determine if this impacts anywhere else.

Impact

What kind of vulnerability is it? Who is impacted?

This vulnerability can lead to Hydra head participant de-sync, stale deployments, and social attacks.

Severity

Moderate

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
High
Privileges required
Low
User interaction
Required
Scope
Unchanged
Confidentiality
None
Integrity
High
Availability
None

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:U/C:N/I:H/A:N

CVE ID

CVE-2025-48886

Weaknesses

No CWEs

Credits