What changed, and why it matters
This commit fixes a programming mistake where a background task was being cancelled from the wrong thread, which could crash the NWC (Nostr Wallet Connect) plugin with a RuntimeError. The fix makes sure the cancellation happens on the correct asyncio thread. It is a reliability/bug-fix patch, not a security vulnerability that an attacker can directly exploit.
Treat as a normal stability fix. No urgent security response required. Users of the NWC plugin should update to avoid the crash when connections change.
Security signals we found
Thread-safety violation in asyncio task cancellation
Crash-only symptom (RuntimeError), no privilege escalation or data exposure evident
Fix uses existing helper run_sync_function_on_asyncio_thread
Evidence from the diff
In electrum/plugins/nwc/nwcserver.py, restart_event_handler() previously called self.event_handler_task.cancel() from a non-asyncio thread, violating asyncio’s thread-safety rules and raising RuntimeError. The patch routes the cancel() call through run_sync_function_on_asyncio_thread(…, block=True) so it executes on the event loop’s own thread. This is a thread-safety correctness fix; it does not address an externally exploitable security flaw.
Changed components
electrum/plugins/nwc/nwcserver.pyNWCServer.restart_event_handlerInspect captured patch +2 / −2
diff --git a/electrum/plugins/nwc/nwcserver.py b/electrum/plugins/nwc/nwcserver.py
index 7823b33..112859c 100644
--- a/electrum/plugins/nwc/nwcserver.py
+++ b/electrum/plugins/nwc/nwcserver.py
@@ -39,7 +39,7 @@ from electrum.plugin import BasePlugin, hook
from electrum.logging import Logger
from electrum.util import log_exceptions, ca_path, OldTaskGroup, get_asyncio_loop, InvoiceError, \
LightningHistoryItem, event_listener, EventListener, make_aiohttp_proxy_connector, \
- get_running_loop
+ get_running_loop, run_sync_function_on_asyncio_thread
from electrum.invoices import Invoice, Request, PR_UNKNOWN, PR_PAID, BaseInvoice, PR_INFLIGHT
from electrum import constants
from electrum.lnutil import RECEIVED
@@ -278,7 +278,7 @@ class NWCServer(Logger, EventListener):
def restart_event_handler(self) -> None:
"""To be called when the connections change so we restart with a new filter"""
if self.event_handler_task:
- self.event_handler_task.cancel()
+ run_sync_function_on_asyncio_thread(self.event_handler_task.cancel, block=True)
@event_listener
def on_event_proxy_set(self, *args):
Why this scored 22/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.