discovery: add panic recovery for serial announce signatures processing
What changed, and why it matters
This update adds a safety net around a specific message-handling path in LND's gossip subsystem. Previously, a crash while handling an AnnounceSignatures1 message could bring down the whole gossip component; now the code catches such crashes and keeps running. The change is defensive hardening rather than a fix for a known active attack.
Treat as routine defensive hardening. Review whether other serial message paths lack panic recovery, and monitor for any future crash reports in this code path. No immediate incident response is indicated by the commit alone.
Security signals we found
panic recovery added to serial message-processing path
prevents gossiper crash from unhandled panic in AnnounceSignatures1 handling
defensive hardening, no logic change to validation or state transitions
Evidence from the diff
The commit wraps the serial processing of lnwire.AnnounceSignatures1 in an anonymous function with deferred panic recovery via d.finalizeGossipProcessing. This prevents a panic in processNetworkAnnouncement from crashing the networkHandler goroutine, while preserving serial execution semantics. The jobID is nil because AnnounceSignatures1 bypasses the validation barrier.
Changed components
discovery/gossiper.goAuthenticatedGossiper.networkHandlerAnnounceSignatures1 processing pathInspect captured patch +26 / −12
diff --git a/discovery/gossiper.go b/discovery/gossiper.go
index dcf77e3..976f2cc 100644
--- a/discovery/gossiper.go
+++ b/discovery/gossiper.go
@@ -1521,19 +1521,33 @@ func (d *AuthenticatedGossiper) networkHandler(ctx context.Context) {
// Channel announcement signatures are amongst the only
// messages that we'll process serially.
case *lnwire.AnnounceSignatures1:
- emittedAnnouncements, _ := d.processNetworkAnnouncement(
- ctx, announcement,
- )
- log.Debugf("Processed network message %s, "+
- "returned len(announcements)=%v",
- announcement.msg.MsgType(),
- len(emittedAnnouncements))
-
- if emittedAnnouncements != nil {
- announcements.AddMsgs(
- emittedAnnouncements...,
+ // Process in an anonymous function so we can
+ // recover from any panics without crashing the
+ // main networkHandler goroutine. We pass nil
+ // for jobID since AnnounceSignatures bypass the
+ // validation barrier.
+ func() {
+ defer d.finalizeGossipProcessing(
+ ctx, "processing",
+ announcement, nil,
)
- }
+
+ //nolint:ll
+ emittedAnnouncements, _ := d.processNetworkAnnouncement(
+ ctx, announcement,
+ )
+ log.Debugf("Processed network "+
+ "message %s, returned "+
+ "len(announcements)=%v",
+ announcement.msg.MsgType(),
+ len(emittedAnnouncements))
+
+ if emittedAnnouncements != nil {
+ announcements.AddMsgs(
+ emittedAnnouncements...,
+ )
+ }
+ }()
continue
}
Why this scored 57/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.