Skip to content

Vulnerability Disclosure: Another Memory Exhaustion DoS in Core Lightning

Summary

Following up on my previous disclosure, I am releasing details on a third Denial-of-Service (DoS) vulnerability in Core Lightning (CLN). This vulnerability allowed a remote peer to trigger unbounded memory growth in the gossip daemon (gossipd), leading to an Out-of-Memory (OOM) system crash.

This vulnerability has been patched in Core Lightning release v26.06rc2. All node operators are advised to upgrade accordingly.

Background

Core Lightning (CLN) uses a multi-daemon architecture, meant to isolate faults. The Lightning Network relies on a “gossip” protocol to propagate channel announcements, channel updates, node announcements, etc. In Core Lightning (CLN), the gossip daemon is responsible for managing this global view of the network.

Because the network can be highly noisy, gossipd must operate efficiently. Furthermore, since it processes untrusted external input, it must be robust against malicious messages.

Discovery

I discovered this vulnerability while verifying the fix for another memory exhaustion DoS vulnerability that I had disclosed earlier during my Summer of Bitcoin 2025 internship: a bug that caused unbounded memory growth in a different daemon, connectd. Details of that vulnerability can be viewed here.

Vulnerability

A remote attacker can trigger a denial-of-service (DoS) condition in the gossipd sub-daemon by flooding it with a high volume of channel_update gossip messages. This causes an internal short_channel_id (SCID) map within gossipd to grow without bounds, allocating memory for each new SCID. The process eventually consumes all available system RAM, leading to extreme system unresponsiveness and a complete freeze (swap death), effectively crashing the node.

The root cause is an unbounded resource allocation in gossipd’s map for tracking unknown SCIDs: unknown_scids. add_unknown_scid() inserts unrecognized SCIDs into this internal integer map. A continuous stream of unique, bogus SCIDs causes this map to grow infinitely.

Worse, no warnings or indications of the ongoing memory consumption are logged as it quietly swells into the gigabytes.

Verification

This vulnerability is triggerable using the exact same attack program as the previous memory exhaustion vulnerability I disclosed. The program acts as a malicious Lightning Network peer that connects to a CLN node and orchestrates a message flood to trigger the crash:

  • Initialization and Connection: The attacker connects to the victim CLN node.

  • Initial Handshake: The attacker completes the init message handshake with the victim.

  • The Malicious Flood: The attacker begins sending a continuous, high-volume stream of channel_update gossip messages to the victim node.

  • Unbounded Queue Growth and Crash:

    • gossipd processes the incoming updates via handle_recv_gossip(). Because the SCIDs are unrecognized, the daemon assumes it missed the original announcements and passes them to query_unknown_channel().
    • To remember to query peers for these missing channels, the daemon calls add_unknown_scid(), which inserts every unique, fake SCID into an internal integer map (uintmap).
    • The uintmap continuously allocates memory to split its internal nodes (split_node()) causing memory consumption of gossipd to balloon indefinitely.

Criticality

  • Severity: Medium/High (DoS)

  • Attack Vector: Remote (Peer-to-Peer)

  • Consequence: A remote attacker can reliably crash any publicly accessible CLN node by flooding it with peer-to-peer traffic. This requires no on-chain funds or channel relationship, making it a potent vector for disrupting network liquidity.

Fix

The reasoning behind storing channel_update messages internally is to not lose out on gossip for a channel that we haven’t discovered yet. This allows us to faster reach the latest state of a channel whose channel_announcement comes in later, eliminating the need for the channel’s peer to rebroadcast the gossips.

However, storing too many of these updates opens the door to vulnerabilities. Fortunately, Rusty Russell (@rustyrussel) had already been working on a PR that introduced an automatic compaction (garbage collection) mechanism for the gossip map. This patch introduces a new function that queries the store for the number of live and dead records, triggering a compaction if there are at least four times as many dead records as live ones (num_dead < 4 * num_live). This PR inadvertently fixed the issue at hand.

More details can be accessed at the fix’s Pull Request.

Timeline

  • 15/05/2026: Vulnerability confirmed using the attack program.

  • 17/05/2026: Investigation perfromed. Cause of the memory usage pinpointed.

  • 18/05/2026: Final vulnerability report sent to CLN’s security mailing list.

  • 21/05/2026: Reply by Rusty confirming the issue and disclosing the supposed fix.

Lessons Learned

This bug would have been found (and perhaps patched) sooner if someone had actually run the attack program I provided in my last disclosure. It is a fortunate coincidence that Rusty was revising the gossmap compaction code around the same time, which happened to implement a fix for this issue.

I had already posted the vulnerability disclosure for the previous memory exhaustion DoS before finding this specific issue on my own. Because of this, it was very much possible that a malicious actor could have seen that post, reproduced the attack program, and utilized this (unknown at the time) attack path.