plugin: nwc: handle encryption scheme signaling
What changed, and why it matters
This is a small, defensive update to Electrum's Nostr Wallet Connect (NWC) plugin. It adds a way for the wallet server to tell clients which encryption methods it supports, and to reject requests that use an unsupported encryption method. This is a standards-compliance and hardening change, not a fix for an active security flaw.
No urgent action required. Treat as a normal hardening/standards-compliance patch. Users running the NWC plugin should update in due course, but there is no evidence of an exploitable vulnerability being fixed.
Security signals we found
Adds explicit input validation for the 'encryption' tag in NWC request events
Adds server-side advertisement of supported encryption schemes in info events
Rejects unsupported encryption schemes with a dedicated error response
Maintains backwards compatibility by continuing to support nip04 as the default scheme
Evidence from the diff
The commit implements NIP-47 encryption scheme signaling in electrum/plugins/nwc/nwcserver.py. It introduces SUPPORTED_ENCRYPTION_SCHEMES = {‘nip04’}, advertises supported schemes in the info event tags, and rejects incoming events tagged with an unsupported ‘encryption’ value via send_error(…, ‘UNSUPPORTED_ENCRYPTION’, …). Previously the server did not signal or validate encryption schemes. The change is backwards-compatible because ‘nip04’ remains the implicit default in NIP-47.
Changed components
electrum/plugins/nwc/nwcserver.pyNWCServer request handling loopNWCServer info event publicationInspect captured patch +13 / −4
diff --git a/electrum/plugins/nwc/nwcserver.py b/electrum/plugins/nwc/nwcserver.py
index 6945a6b..b189abf 100644
--- a/electrum/plugins/nwc/nwcserver.py
+++ b/electrum/plugins/nwc/nwcserver.py
@@ -183,6 +183,7 @@ class NWCServer(Logger, EventListener):
SUPPORTED_METHODS: set[str] = {'make_invoice', 'lookup_invoice', 'get_balance', 'get_info',
'list_transactions', 'notifications'}.union(SUPPORTED_SPENDING_METHODS)
SUPPORTED_NOTIFICATIONS: list[str] = ["payment_sent", "payment_received"]
+ SUPPORTED_ENCRYPTION_SCHEMES: set[str] = {'nip04'}
def __init__(
self,
@@ -328,6 +329,13 @@ class NWCServer(Logger, EventListener):
await self.send_error(event, "OTHER", f"not handling too old request")
continue
+ # check encryption scheme
+ for tag in event.tags:
+ if len(tag) == 2 and tag[0] == 'encryption':
+ if tag[1] not in self.SUPPORTED_ENCRYPTION_SCHEMES:
+ await self.send_error(event, "UNSUPPORTED_ENCRYPTION", " ".join(self.SUPPORTED_ENCRYPTION_SCHEMES))
+ break
+
# decrypt the requests content
our_secret: str = self.connections[event.pubkey]['our_secret']
our_connection_secret = PrivateKey(raw_secret=bytes.fromhex(our_secret))
@@ -875,10 +883,11 @@ class NWCServer(Logger, EventListener):
We publish one info event for each client connection.
https://github.com/nostr-protocol/nips/blob/75f246ed987c23c99d77bfa6aeeb1afb669e23f7/47.md#example-nip-47-info-event
"""
+ tags = []
if self.SUPPORTED_NOTIFICATIONS:
- tags = [['notifications', ' '.join(self.SUPPORTED_NOTIFICATIONS)]]
- else:
- tags = None
+ tags.append(['notifications', ' '.join(self.SUPPORTED_NOTIFICATIONS)])
+ if self.SUPPORTED_ENCRYPTION_SCHEMES:
+ tags.append(['encryption', ' '.join(self.SUPPORTED_ENCRYPTION_SCHEMES)])
for client_pubkey, connection in list(self.connections.items()):
supported_methods = self.SUPPORTED_METHODS.copy()
if self.is_receive_only(client_pubkey):
@@ -887,7 +896,7 @@ class NWCServer(Logger, EventListener):
event_id = await aionostr._add_event(
self.manager,
kind=self.INFO_EVENT_KIND,
- tags=tags, # only needed if we support notification events
+ tags=tags or None,
content=content,
private_key=connection['our_secret']
)
Why this scored 18/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.