# Vulnerability Disclosure: Assertion DoS in Core Lightning

**URL:** <https://delvingbitcoin.org/t/vulnerability-disclosure-assertion-dos-in-core-lightning/2507>\
**Category:** Implementation\
**Tags:** lightning, fuzz\
**Created:** [May 16, 2026, 1:23pm UTC](https://delvingbitcoin.org/t/vulnerability-disclosure-assertion-dos-in-core-lightning/2507 "2026-05-16T13:23:53Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![Chand-ra](https://delvingbitcoin.org/user_avatar/delvingbitcoin.org/chand-ra/32/2064_2.png) [@Chand-ra](https://delvingbitcoin.org/u/Chand-ra)\
**Post date:** [May 16, 2026, 1:23pm UTC](https://delvingbitcoin.org/t/vulnerability-disclosure-assertion-dos-in-core-lightning/2507/1 "2026-05-16T13:23:53Z")

</div>

## Summary

During my [Summer of Bitcoin](https://www.summerofbitcoin.org/) 2025 internship, I discovered a [Denial-of-Service](https://en.wikipedia.org/wiki/Denial-of-service_attack) (DoS) vulnerability in [Core Lightning](https://github.com/ElementsProject/lightning) (CLN) that allowed a remote peer to crash a node by sending a specifically crafted message. The issue was caused by an overly strict assertion in [`openingd`](https://github.com/ElementsProject/lightning/tree/master/openingd)’s logic.

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

## Background

Core Lightning (CLN) uses a multi-daemon architecture. When a peer connects and attempts to open a channel, a specific sub-daemon (`openingd`) is spawned to handle the channel-opening process. This architecture is designed to isolate faults. If a crash occurs somewhere, it shouldn’t take down the whole node.

However, certain crashes, if they occur in critical paths, can lead to a node-wide crash.

## Discovery

This vulnerability was discovered using a new [fuzz target](https://github.com/google/fuzzing/blob/734e55f3cfed1adbb51bf6cb5c65b4c1197b7089/docs/why-fuzz.md) I developed, `fuzz-open_channel`. The target tries to do one of these two things at random: create an [`open_channel` message](https://github.com/lightning/bolts/blob/aff897f8f6ac0a7ba071b3b61fede7dc813be0b5/02-peer-protocol.md#the-open_channel-message) with the following properties:

- **Structural Validity:** Messages should pass the initial wire-protocol checks (length, type).

- **Semantic Randomness:** Randomizes the actual content (feature bits, channel flags, TLVs) using fuzzer’s data to test edge-case logic deep within the target’s state machine.

Or create an `open_channel` message that is completely random (use the fuzzer’s data as the message, straight up). The target then feeds this message to the parser for `open_channel` messages: [`fundee_channel()`](https://github.com/ElementsProject/lightning/blob/611e2620995f2c6ce5a509daf0da6c7c1c824b24/openingd/openingd.c#L826). When hit with a specific message type, the parser raises a `SIGABRT` signal, which is subsequently caught and flagged by [`AddressSanitizer`](https://github.com/google/sanitizers/wiki/AddressSanitizer).

For more details about the target, see the correspoding [Pull Request](https://github.com/ElementsProject/lightning/pull/8411).

## Vulnerability

The [`HSMD`](https://github.com/ElementsProject/lightning/blob/abb0cddaaac233c89ab9dd6e3fde9e68c9824168/hsmd/hsmd.c) in CLN expects a valid `funding_txid` within the [`funding_created` message](https://github.com/lightning/bolts/blob/aff897f8f6ac0a7ba071b3b61fede7dc813be0b5/02-peer-protocol.md#the-funding_created-message) during the [channel establishment](https://github.com/lightning/bolts/blob/aff897f8f6ac0a7ba071b3b61fede7dc813be0b5/02-peer-protocol.md#channel-establishment-v1). [`handle_setup_channel()`](https://github.com/ElementsProject/lightning/blob/7343502c69258535ddde6c206922b5616f9efc85/hsmd/libhsmd.c#L366) within `hsmd/libhsmd.c` performs an [assertion check](https://github.com/ElementsProject/lightning/blob/7343502c69258535ddde6c206922b5616f9efc85/hsmd/libhsmd.c#L400): `!mem_is_zero(&funding_txid, sizeof(funding_txid))`. This assertion fails when the `funding_txid` is all zeros, as provided by the malicious message.

The assertion was intended to guarantee a specific state transition was impossible, but the fuzzer managed to manipulate the message in a way that the original developers assumed was unreachable. The `assert()` failed, and the daemon called `abort()`, killing the process.

## Verification

An attack program was created to verify the vulnerability. The program acts as a malicious Lightning Network peer that connects to a CLN node and orchestrates a specific message sequence to trigger the crash:

- _Initialization and Connection_: The attacker connects to the victim CLN node.

- _Initial Handshake_: The attacker completes the [`init` message](https://github.com/lightning/bolts/blob/aff897f8f6ac0a7ba071b3b61fede7dc813be0b5/01-messaging.md#the-init-message) handshake with the victim.

- _Channel Open and Accept_: The attacker completes the exchange of [`open_channel`](https://github.com/lightning/bolts/blob/aff897f8f6ac0a7ba071b3b61fede7dc813be0b5/02-peer-protocol.md#the-open_channel-message) and [`accept_channel`](https://github.com/lightning/bolts/blob/aff897f8f6ac0a7ba071b3b61fede7dc813be0b5/02-peer-protocol.md#the-accept_channel-message) messages, using standard acceptable parameters.

- _The Malicious Payload_:

## Criticality

- **Severity:** Medium/High (DoS)

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

- **Consequence:** A remote attacker can reliably crash any CLN node that accepts channels initiated by other nodes.

## Fix

By the time this vulnerability was discovered, Rusty was working on another issue (a crash when you configure a `to-self-delay` of 0) that incidentally fixed this issue as well. More or less, the fix was to get rid of the assertion causing the crash. More details can be accessed at the corresponding [Pull Request](https://github.com/ElementsProject/lightning/pull/8436/).

## Timeline

- **11/07/2025** : Target pushed upstream.

- **12/07/2025-24/07/2025** : Improvements made to the target, dealing with false positives.

- **24/07/2025** : Vulnerability confirmed by Matt using the attack program.

- **25/07/2025** : Ran the attack program locally, draft of the vulnerability report created.

- **28/07/2025** : Vulnerability report sent to CLN’s security mailing list.

- **04/08/2025** : Reply by Rusty confirming the issue and disclosing the supposed fix.

- **07/08/2025** : Fix merged to `master`.

## Lessons Learned

This bug highlights the power of fuzzing for finding “Unknown Unknowns.” No human developer wrote a test case for this specific state combination because “it shouldn’t happen.” The fuzzer, having no knowledge of what should happen, simply tried it and proved that it could happen.

_Special thanks to my mentor [Matt Morehouse](http://github.com/morehouse/) for guiding the entire process, especially the triage and disclosure._
