Subject: [bitcoindev] Full-Disclosure: CVE-2025-27586 "No Santa Claus under the Lightning Sun"

From: Antoine Riard <[email-masked]>
Date: Thu, 12 Jun 2025 12:03:30 -0700 (PDT)

Hi,

This report is to disclose a vector of attack affecting bitcoin 
time-sensitive
contract protocols, specifically the lightning network by exhausting the 
fee-bumping
reserves of anchor-upgraded channels of a lightning node.

This attack vector has been known since the early days of anchor output 
deployment
over the network circa end of 2020 and it has been discussed among LN 
maintainers
since circa mid 2022. While few basic mitigations have been developed and 
shipped
in LN implementations over the last few years, it is believed that more 
robust
mitigations can only be deployed at the protocol-level, thus unlikely to 
happen
with an embargoed process.

This class of attacks dubbed "fee-bumping reserves exhaustion attacks" is
tracked at the protocol-level by CVE-2025-27586. As as far as it is 
understood
it is affecting LN routing nodes (i.e a double-spent of an incoming / 
outgoing 
HTLC) and LN payee (i.e revealing a preimage with `update_fulfill_htlc` and
double-spent with a HTLC-timeout). This is indeed a money stealing kind of 
attacks.

While the attacks have not been tested under real-world configurations, 
they're
deemed as feasible, with the caveat of round guessing the level of 
fee-bumping
reserves for the adversary (see corresponding section). If you're running a
LN node with subsequent funds at stake and deployed `option_anchor` channels
channels, I uphold to reach out to the maintainers of your run LN 
implementations
for tailored recommendations on how to adjust your fee-bumping reserves 
(some
LN implementations are monolothic stacks, some are more modular not 
shipping with
a wallet and here efficient mitigations is very tight with your L1 wallet).

The report is organized in the following fashion:
- background on LN fee-bumping
- explanation of the problem
- the challenge: detecting a node fee-bumping reserves from the outside
- lightning mitigations
- second-layers impact
- discovery
- timeline

A copy of the report is available here if formatting doesn't work well:
https://ariard.github.io/feebumping.html

## Background: Lightning Fee Estimation, Legacy Channel and `option_anchor`

Historically, the responsibility for fees has been on the channel initiator
(i.e the channel forwarding first the `open_channel` msg). The fees feeding
both counterparties commitment transaction is substracted from the initiator
balance (`funding.is_outbound()` in LDK). The feerate determinating the 
level
of absolute fees committed is set by the flow of `update_fee` message.

That msg is forward by the channel initiator with a `feerate_per_kw`. If
the recipient estimates from its local fee-estimation that the feerate is
good enough for timely processing and not unreasonably large, the feerate is
accepted. This feerate is used to build the local and remote's versions
of the commitment transactions and the respective set of second-stage HTLC
transactions (`build_htlc_transaction()` in LDK).

With this legacy mode of fee-bumping, all the fee-bumping liquidity is 
coming out of the channel initator balance (i.e the `to_local` or 
`to_remote`
output accordingly), of which this balance is theorically the upper limit
to fee-bump a version of the commitment tx and its second-stage HTLCs.

As of today, this `update_fee` mechanism is still supported by LN implems
and this mechanism is still part of the BOLTs specification (BOLT #2 
"Updating
Fees: `update_fee`). However, as it has been well-established and understood
by the LN community since a long time, this mechanism does not work very 
well
in an environment with dynamic fees. Indeed, the pre-signed feerates at time
T might not suffice to get into a block at time T + 100. Additionally, there
is no guarantee that the channel counterparty is online or cooperative at 
time
T + 100 to re-sign a pair of commitment transaction with enhanced feerates.

Therefore, since 2018, the LN community has been working on the anchor 
output
upgrade, i.e adding a pair of dedicated outputs on each version of the 
commitment
transaction (i.e historically `option_anchor_outputs` then 
`option_anchors_zero_fee_htlc_tx`,
now `option_anchors`). This anchor output mechanism allows a LN node to 
attach
unilaterally a child-pay-for-parent on the commitment transaction it has to
include in a block.

Making abstraction of any transaction-relay issue, the CPFP can constitute a
fee-bump of the overall package (the commitment tx + the cpfp tx), which is
increasing its feerate to increase the odds its block inclusion. In case of
time-sensitive HTLC outputs to claim (e.g a HTLC-preimage to claim a 
"received"
output or a HTLC-timeout to claim a "offered" output), timely inclusion in
blocks matters for a LN node.

As of today, the `option_anchor` is not the default for LDK (v0.0.124 -
src/util/config.rs), is the default for LND (v.19.0-beta - sample-lnd.conf),
is the default for Core-Lightning (v.25.02 - lightningd/options.c). Eclair 
has 
not been checked because it's in Scala.

## Problem: Lack of Fee-Reserves Provisioning for Anchor Outputs Fee-Bumping

While the anchor output mechanism allows non-interactive fee-bumping of
a commitment transaction, the original specification of anchor output never
mentions, neither indicates how the now external fee-bumping reserves should
be provisioned LN node and if any reactive actions should be undertake in
face of network mempools congestions or high block inclusion median feerate 
[1].

The lack of fee-reserves provisioning exposes a LN node to a fee-bumping
reserve exhaustion attack, where a malicious counterparty triggers inflation
of the LN node's channel surface to exhaust the limited fee-bumping 
reserves.

E.g if Alice's commitment transaction is pre-signed at 1 sat / vb, the
current size is 2000 bytes and the top block feerates ranks at 10 sat / vb,
Alice should have at least 19000 sats of fee-bumping reserves.

Still, even if Alice has a sufficient level of reserves, if the channel's
`max_accepted_htlcs` is uncapped (i.e up to the protocol limit of 483 HTLCs
one-side), the channel counterparty Bob can inflate the size of the 
commitment
transaction (e.g from 2000 bytes to 4000 bytes) up until Alice's fee-bumping
reserves are exhausted.

E.g if Alice, a routing node, has a pending HTLC of value 30k sats, and she 
has
only 20k satoshis of reserves, if the block feerate is to be over 10 sats / 
vbyte
up until the HTLC expires at block T=150, she won't be able to include her 
commitment
tx, before an incoming HTLC expires at block T=100.

In the lack of a monitored `max_channel_weight_surface` for each opended 
channel
binded with fee-bumping reserves, a LN node is exposed to diverse 
fee-bumping
reserve exhaustion attacks.

Generally, there are 3 injection vectors that a LN counterparty, or a 
third-party
that can route through a channel opened with the target node, to inflate a 
LN node
global channel surface:
- opening more inbound channels
- asks for more outbound channels (e.g by buying Just-in-Time channels)
- routing more offered / received HTLCs on an existent given channel

This class of attacks is dependent on the level of networks mempools 
congestion,
as with more congestions spikes in, more channels are exposed to the 
attack. The
attack difficulty of execution is deemed as medium, as only direct peering 
or
indirect peering with the target node is necessary and visibility on the 
ongoing
networks mempools congestion.

For what is concerning, the adversy cost, it is limited as the on-chain fees
to open more inbound channels, out-of-band fees to open more outbound 
channels.
It is unfairly cheap if the attack vector of routing HTLCs to inflate the 
size
of the LN channel is leveraged, as off-chain fees are only currently paid in
case of success for LN. An adversary only has to overbid at the current 
block
inclusion feerate and the break even threshold is reached as long as the 
HTLC's
`amount_msat` is superior to the fee cost.

## Detecting a Node Fee-Bumping Reserves from the Outside

There is one main challenge for an adversary which is worth of awareness, 
namely
guessing the fee-bumping level of reserves of a target node, before to 
launch
a fee-bumping reserve attack. Indeed, while LN implementations have 
pre-configured
level of fee-bumping reserves automatically allocated which can be observed 
from
the code source of the diverse LN implementations, a LN node could have 
consequential
UTXO reserves in one or more L1 wallets.

A first deanonymization heuristic to bound the fee-bumping reserves level 
can be
to trigger a unilateral force close with a "decoy" test. E.g at block 
inclusion feerate
X, for 2 public channels provokes a force-close of channel 1 and observe if 
the
target node Y is going to match the inclusion feerate for X with its CPFP 
attached
to channel 1. If yes, the adversary can estimate that the same level of 
reserves holds
for channel 2. If no, the adversary can estimate that public channel is 
probably
exposed to a FBRE attack.

This deanonymization heuristic can be generalized on long-tend stastical 
observations
of a LN node by snitching all its unilateral force-closures from the 
on-chain txn logs.

A second tupe deanonymization heuristic can be to observe the interactions 
with
the base-layer and the UTXO management, e.g based on which BTC addresses 
are consumed
to feed the outbound channels opening, or the dual-funding channel opening 
by the
target node (i.e all the operations of replenishment, funding, payment, 
settlement
or collection) [2].

One should make the observations that for L1 wallets coins to be leveraged 
as
fee-bumping reserves, the L1 wallet should be sufficently "hot" to be used 
in the
time span granted by the lowest safety timelock for a deployed channel.

## Lightning Mitigations

On the range of mitigations that can be implemented by a LN implementation
there are 3 complementary plausible lines:
- 1) over-provisioning fee-bumping reserves
- 2) halting the increase of the LN node's all-channels's 
`max_channel_weight_surface`
- 3) cooperatively collaboring with LN peers to downcrease its local 
`max_channel_weight_surface`.

About the 1), which is the more obvious, the idea is for a LN node to 
over-provision
the fee-bumping reserves with the following formula: 
`current_opened_channel` *
`max_channel_weight_surface` * `worst_case_feerate_per_kw` / 1000. For the 
`worst_case_feerate_per_kw`,
it's the hardest parameter to select, as while historical worst mempools 
network congestion
level are good empirical points, there are no guarantee of the future 
worst-case level of
congestion. Over-provisioning fee-bumping reserves for a node is coming 
with a high liquidity
downside.

About 2), the idea is to stop accepting inbound channels, if the local 
level of fee-bumping
reserves is falling under implemenetation-defined or operation-defined 
threshold. E.g Core-Lighting
has a `min-emergency-msat` option field tfor that purpose. This threshold 
can be extended for
outbound channel reserve and the addition / removal of HTLCs outputs on a 
commitment transactions,
i.e to reject HTLCs if the local fee-bumping reserves is too low.

About 3), the idea is along a payment path, the LN node partaking in the 
routing of the
HTLC could collaborate to unlash the locked HTLC on each hop, starting by 
the end to
allow each local node to compress their commitments transaction size. This 
would assume
some kind of interactivity happening successfully among each pair of LN 
nodes, and a new
option in the `node_announcement`, e.g `option_unlock_htlc`. It can be 
especially valuable 
for long-term HTLC kind of traffics (e.g the ones for swaps).

The LN implementations (LDK, LND, Core-Lighting, Eclair) implements 
different levels
of those mitigations. It is an open research question if more types of 
practical
mitigationscan be envisioned, implemented and deployed.

## Second-Layers Impact

As far as it's understood, this class of fee-bumping reserves attacks
is generally affecting any contract protocol or multi-party transactions,
where counterparties have a competing interest in concurrent and exclusive
confirmations of a set of transactions. In the presence of anchor output,
though in the lack of dynamic fee-bumping reserves management carefully
implemented, all lead to think use-cases described following the "contract
protocol" pattern can be more or less affected.

## Discovery

In 2020, a draft for anchor output submitted to the bolts. The anchor output
upgrades is designed to be a complete overhaul of the dynamic fee-management
for lightning channels, in a move way static fees only legacy channels. 
Initial
finding of economic pinning against lightning commitment and second-stage 
HTLC
transactions.

End of 2020, in the context of implementing a first version of anchor output
in rust-lightning [0], I realize that **spoiler alert** (a) Santa Clause 
does not
exist, as such (b) there will be no one to magically fulfill a lightning 
node
fee-bumping reserves for `option_anchor_outputs` just on time in case of 
unilateral
force-closure of a channel. This state of things could open the door to a 
counterparty
inflating the number of opened channels and their weight units sizes to 
induce
adversarial exploitations.

Being already busy with numerous other vulnerabilities at the time in 2020, 
including
the one that lead to the transition from `option_anchor_outputs` to 
`option_anchors_zero_fee_htlc_tx`
[4], I only reported the finding to a selected group of LN maintainers and 
devs in
July 2022. From then on, attacks vectors and ideas of efficient mitigations 
have been
discussed.

## Timeline

- 2022-07-11: Report of the finding to XXX, Bastien Teinturier (Eclair), 
Lisa Neigut
(C-lightning), YYY and Eugene Siegel (LND)
- 2022-07-17: Sharing to Olaoluwa Osuntunkun (LND)
- 2023-05-25: Sharing to Rusty Russell (C-Lightning), Fabrice Drouin 
(Eclair) and ZZZ
- 2023-07-25: Full disclosure put on ice until anchor output support in LDK
- 2025-02-27: Proposal of a full disclosure date in early weeks of June.
- 2025-03-03: CVE assigned by MITRE
- 2025-06-16: Full disclosure of CVE-2025-27586 and fee-bumping reserve 
exhaustion attacks

## Conclusion 

In this report, a new protocol-level attacks against bitcoin time-sensitive 
contract
protocols, specifically the LN, was introduced by exploiting the lack of a 
fee-reserves
provisioning mechanism to provide on-time sufficient fees amount for 
fee-bumping CPFP
attached on anchor output. This attack appears to be plausible against 
`option_anchors`
lightning channels funds under real-world scenario, while it deserves 
indeed more
investigation and experiment.

One challenge is effectively exploiting this vector of attacks is roughly 
guessing
the level of fee-bumping reserves available to the target LN node. While 
adequate
provisioning or just-in-time halting of the increase of a LN node all 
channels's
`max_channel_weight_surface` consistute a robust mitigation, more 
mitigations at
the protocol-level might alleviate the stuck liquidity burden coming as a 
downside
of such mitigations.

Do not trust, verify. All mistakes and opinions are my own.

Antoine

[0] https://github.com/lightningdevkit/rust-lightning/pull/642
[1] https://github.com/lightning/bolts/pull/688
[2] https://arxiv.org/abs/2007.00764
[4] 
https://diyhpl.us/~bryan/irc/bitcoin/bitcoin-dev/linuxfoundation-pipermail/lightning-dev/2020-September/002800.txt 

-- 
You received this message because you are subscribed to the Google Groups "Bitcoin Development Mailing List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email-masked].
To view this discussion visit https://groups.google.com/d/msgid/bitcoindev/fe76185f-8d9c-41b2-ab15-117d7787a204n%40googlegroups.com.