Skip to content

lightningd: accept OP_RETURN closer_scriptpubkey in simple-close check#9292

Open
nGoline wants to merge 1 commit into
ElementsProject:masterfrom
nGoline:fix/simpleclose-opreturn-force-close
Open

lightningd: accept OP_RETURN closer_scriptpubkey in simple-close check#9292
nGoline wants to merge 1 commit into
ElementsProject:masterfrom
nGoline:fix/simpleclose-opreturn-force-close

Conversation

@nGoline

@nGoline nGoline commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

Under option_simple_close, a peer's closing_complete may set closer_scriptpubkey to a spec-valid OP_RETURN (BOLT2 permits it when the closer treats its output as uneconomical). closingd accepts and signs the closing tx, but master's close_tx_check validated every output against the two stored shutdown scripts only, so the OP_RETURN output matched neither, master rejected our own signed tx via channel_internal_error, and the channel force-closed.

This was remotely triggerable by any peer once the feature is negotiated.

The fix is to accept an output that is a valid, zero-value OP_RETURN, but only when option_simple_close is negotiated and only after the LOCAL-script match. Our own output is always paid to shutdown_scriptpubkey[LOCAL], so an OP_RETURN matching neither stored script can only be the peer's closer_scriptpubkey. Being unspendable and zero-value, accepting it preserves the check's anti-exfiltration property.
Kept master-side rather than whitelisting subd-reported negotiated scripts + validating in the signer since that would weaken the trusted-state check and require an HSM-protocol change affecting external signers (VLS).

Added lightningd/test/run-close_tx_check.c, which covers the accept path, feature-gating, non-zero-value rejection, and that unknown spendable scripts stay rejected. Verified to fail without the fix.

Reported by @0xaudron via the security process. option_simple_close is experimental (--experimental-simple-close, off by default) and unreleased, meaning no production exposure.

@nGoline nGoline added this to the v26.09 milestone Jul 7, 2026
@nGoline nGoline requested a review from cdecker July 7, 2026 16:50
A peer's closing_complete may set closer_scriptpubkey to a spec-valid
OP_RETURN, but close_tx_check only whitelisted the two stored shutdown
scripts, so master rejected our own signed tx and force-closed the
channel.  Accept a zero-value OP_RETURN output, only when
option_simple_close is negotiated.  Adds a regression test.

Reported-by: 0xaudron
Changelog-None: option_simple_close is experimental and unreleased.
@nGoline nGoline force-pushed the fix/simpleclose-opreturn-force-close branch from f69bac7 to c325683 Compare July 7, 2026 17:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant