What changed, and why it matters
This commit fixes a crash in Core Lightning's 'askrene' routing plugin. The bug occurred when calculating fees for a single payment path: if a channel fee was too large to fit in a 32-bit unsigned integer, the code would skip adding the arc to the network, leaving it uninitialized. Later code could then hit an assertion and crash the plugin. The fix uses the full 64-bit fee value directly instead of trying to squeeze it into a smaller integer type. A previously-skipped regression test is now re-enabled.
Apply the patch and run the re-enabled test_excessive_fee_cost regression test. Monitor for any other u32 conversions of millisatoshi values in askrene that could silently truncate or skip large values.
Security signals we found
plugin crash / local DoS
integer-width truncation avoided
uninitialized cost array element leading to assertion failure
regression test re-enabled
Evidence from the diff
In plugins/askrene/mcf.c, init_linear_network_single_path() previously computed channel fees via amount_msat_to_u32(), and if the fee did not fit in u32 it ‘continue’d without setting (arc_fee_cost)[arc.idx]. The caller then asserts that arcs are initialized, so a skipped arc caused an abort. The patch removes the u32 conversion and stores fee.millisatoshis directly (annotated / Raw: fee cost */). The test_excessive_fee_cost regression test in tests/test_askrene.py is un-skipped. The crash is a local denial-of-service to the askrene plugin process, not a remote network exploit or funds loss.
Changed components
plugins/askrene/mcf.ctests/test_askrene.pyaskrene plugin single-path solverInspect captured patch +1 / −5
diff --git a/plugins/askrene/mcf.c b/plugins/askrene/mcf.c
index a59c6feb..82418f79 100644
--- a/plugins/askrene/mcf.c
+++ b/plugins/askrene/mcf.c
@@ -1157,11 +1157,8 @@ static void init_linear_network_single_path(
c->half[half].base_fee,
c->half[half].proportional_fee))
abort();
- u32 fee_msat;
- if (!amount_msat_to_u32(fee, &fee_msat))
- continue;
(*arc_fee_cost)[arc.idx] =
- fee_msat +
+ fee.millisatoshis + /* Raw: fee cost */
params->delay_feefactor * c->half[half].delay;
}
}
diff --git a/tests/test_askrene.py b/tests/test_askrene.py
index f9b3e6ae..501deebb 100644
--- a/tests/test_askrene.py
+++ b/tests/test_askrene.py
@@ -1961,7 +1961,6 @@ def test_splice_dying_channel(node_factory, bitcoind):
assert set([only_one(r['path'])['short_channel_id_dir'] for r in routes]) == set([pre_splice_scidd, post_splice_scidd])
-@unittest.skip
def test_excessive_fee_cost(node_factory):
"""Produce a arc with very large fee cost that triggers an assertion in
askrene's single path solver."""
Why this scored 44/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.