gossipd: be more robust against channel_update spamming.
What changed, and why it matters
This update fixes a memory exhaustion weakness in Core Lightning's gossip daemon. An unauthenticated remote peer could send a flood of fake Lightning channel identifiers, causing the node to keep allocating memory until the process crashed or the host ran out of memory. The patch caps two internal queues at 10,000 entries so memory use stays bounded.
Upgrade to Core Lightning v26.06rc2 or later. Until upgraded, restrict untrusted peer connections and monitor gossipd memory usage.
Security signals we found
Unbounded memory growth in network-facing daemon
Remote peer can influence memory allocation via protocol messages
Denial-of-service via memory exhaustion
Resource cap added to limit attack surface
Responsible disclosure by independent researcher
Evidence from the diff
The patch addresses unbounded growth of two gossipd resources: the seeker’s unknown_scids uintmap and the daemon_conn queue to lightningd. Previously, a peer could supply unique bogus short channel IDs (SCIDs) that would be inserted into unknown_scids without limit, and channel_update messages for unknown channels could pile up unbounded messages for lightningd. The fix adds an explicit num_unknown_scids counter and rejects new entries once it exceeds 10,000, and drops tell_lightningd_peer_update messages when the daemon_conn queue length exceeds 10,000. This bounds memory consumption and prevents remote memory-exhaustion denial of service.
Changed components
gossipd/gossipd.cgossipd/seeker.cgossipd unknown_scids uintmapdaemon_conn queue to lightningdInspect captured patch +17 / −1
diff --git a/gossipd/gossipd.c b/gossipd/gossipd.c
index b9f45424..3815e173 100644
--- a/gossipd/gossipd.c
+++ b/gossipd/gossipd.c
@@ -328,6 +328,11 @@ void tell_lightningd_peer_update(struct daemon *daemon,
{
struct peer_update remote_update;
u8* msg;
+
+ /* FIXME: Tell connectd to kick out source peer if this happens? */
+ if (daemon_conn_queue_length(daemon->master) > 10000)
+ return;
+
remote_update.scid = scid;
remote_update.fee_base = fee_base_msat;
remote_update.fee_ppm = fee_ppm;
diff --git a/gossipd/seeker.c b/gossipd/seeker.c
index c632e8b8..5c5a6bbf 100644
--- a/gossipd/seeker.c
+++ b/gossipd/seeker.c
@@ -59,6 +59,7 @@ struct seeker {
/* Channels we've heard about, but don't know (by scid). */
UINTMAP(bool) unknown_scids;
+ size_t num_unknown_scids;
/* Channels we've heard about newer timestamps for (by scid). u8 is
* query_flags. */
@@ -150,6 +151,7 @@ struct seeker *new_seeker(struct daemon *daemon)
seeker->daemon = daemon;
uintmap_init(&seeker->unknown_scids);
+ seeker->num_unknown_scids = 0;
uintmap_init(&seeker->stale_scids);
seeker->random_peer = NULL;
u32 gossipers = daemon->autoconnect_seeker_peers > SEEKER_GOSSIPERS ?
@@ -300,6 +302,7 @@ static struct short_channel_id *unknown_scids_remove(const tal_t *ctx,
while (uintmap_first(&seeker->unknown_scids, &scid)) {
scids[i].u64 = scid;
(void)uintmap_del(&seeker->unknown_scids, scid);
+ seeker->num_unknown_scids--;
if (++i == max)
break;
}
@@ -689,10 +692,15 @@ static bool add_unknown_scid(struct seeker *seeker,
struct short_channel_id scid,
struct peer *peer)
{
+ /* We can't know everything! */
+ if (seeker->num_unknown_scids > 10000)
+ return false;
+
/* Check we're not already getting this one. */
if (!uintmap_add(&seeker->unknown_scids, scid.u64, true))
return false;
+ seeker->num_unknown_scids++;
set_preferred_peer(seeker, peer);
return true;
}
@@ -1145,7 +1153,10 @@ bool remove_unknown_scid(struct seeker *seeker,
const struct short_channel_id *scid,
bool found /*FIXME: use this info!*/)
{
- return uintmap_del(&seeker->unknown_scids, scid->u64);
+ if (!uintmap_del(&seeker->unknown_scids, scid->u64))
+ return false;
+ seeker->num_unknown_scids--;
+ return true;
}
/* This peer told us about an update to an unknown channel. Ask it for a
Why this scored 76/100
Evidence and disclosure record
Verified links used to place this patch in context. External claims remain attributed to their publishers.
gossipd: be more robust against channel_update spamming
Upstream patch capping the unknown-SCID map and pending daemon queue at 10,000 entries. The commit explicitly credits Chand Pratap as the reporter.
Twin Memory Exhaustion DoS Vulnerabilities in Core Lightning
Responsible disclosure showing that an unauthenticated remote Lightning peer could supply unique bogus channel IDs, grow gossipd's unknown-SCID map without bound, exhaust host memory, and crash the node. The researcher rates the issue Medium/High and advises operators to upgrade.
Core Lightning v26.06rc2
Core Lightning release notes state that gossipd was made more robust against channel_update spamming. The fix is included in subsequent v26.06 releases.
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.