channeld: reject `closing_complete` and `closing_sig` with a clear error
What changed, and why it matters
This change makes a Lightning node respond with a clear warning error if a peer sends certain closing-related messages at the wrong time, instead of silently following the default 'unknown message' path. It is a hardening fix that prevents potential confusion or protocol mishandling during channel close, but it does not by itself grant an attacker new capabilities.
Treat as a minor hardening patch. Review whether any peer can trigger the new peer_failed_warn path to cause unwanted disconnects, and ensure simpleclosed correctly handles these messages after channeld exits. No urgent deployment required absent a disclosed exploit.
Security signals we found
Explicit rejection of protocol messages that should not occur in this daemon state
Prevents silent handling of closing_complete/closing_sig inside channeld
Uses peer_failed_warn to disconnect with a descriptive error
Evidence from the diff
In channeld/channeld.c, WIRE_CLOSING_COMPLETE and WIRE_CLOSING_SIG are moved from the generic unexpected-message switch block into a new block that calls peer_failed_warn() with an explicit ‘Peer sent unexpected message %s’ string. When option_simple_close is negotiated, simpleclosed is supposed to handle these messages after channeld exits, so their arrival inside channeld is a protocol violation. The patch turns a silent default path into an explicit warning disconnect.
Changed components
channeld/channeld.cWIRE_CLOSING_COMPLETE handlingWIRE_CLOSING_SIG handlingoption_simple_close negotiation pathInspect captured patch +7 / −2
diff --git a/channeld/channeld.c b/channeld/channeld.c
index b2e662fd..3848f0d2 100644
--- a/channeld/channeld.c
+++ b/channeld/channeld.c
@@ -5211,14 +5211,14 @@ static void peer_in(struct peer *peer, const u8 *msg)
case WIRE_TX_ABORT:
check_tx_abort(peer, msg, NULL);
return;
+ case WIRE_CLOSING_COMPLETE:
+ case WIRE_CLOSING_SIG:
case WIRE_INIT:
case WIRE_OPEN_CHANNEL:
case WIRE_ACCEPT_CHANNEL:
case WIRE_FUNDING_CREATED:
case WIRE_FUNDING_SIGNED:
case WIRE_CLOSING_SIGNED:
- case WIRE_CLOSING_COMPLETE:
- case WIRE_CLOSING_SIG:
case WIRE_TX_ADD_INPUT:
case WIRE_TX_REMOVE_INPUT:
case WIRE_TX_ADD_OUTPUT:
@@ -5226,6 +5226,11 @@ static void peer_in(struct peer *peer, const u8 *msg)
case WIRE_TX_COMPLETE:
case WIRE_OPEN_CHANNEL2:
case WIRE_ACCEPT_CHANNEL2:
+ peer_failed_warn(peer->pps, &peer->channel_id,
+ "Peer sent unexpected message %s",
+ peer_wire_name(type));
+ return;
+
case WIRE_TX_SIGNATURES:
handle_unexpected_tx_sigs(peer, msg);
return;
Why this scored 33/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.