Skip to content

Nostr Wallet Connect plugin: daily spending limit bypass

Low
SomberNight published GHSA-q7m2-785w-r585 Apr 28, 2026

Package

electrum

Affected versions

4.6.0<=x<4.7.2

Patched versions

4.7.2

Description

Impact

A malicious or compromised NWC client with a valid NWC connection can spend more than the configured daily spending limit due to:

  1. non-atomic budget check/update under concurrent request handling, and
  2. satoshi truncation of millisatoshi values during budget accounting

Context

  • Electrum has support for external and internal (built-in) plugins.
  • Nostr Wallet Connect is a built-in plugin. Plugins are default disabled.
  • The NWC plugin runs an NWC server that can initiate lightning payments on behalf of the user.
  • The plugin can be configured with a maximum daily spending limit (daily_limit_sat).

Note that depending on the usecase, the NWC client can be conceptually either trusted or untrusted.
Example usecases:

  • running an open-source nostr client such as Amethyst, and using NWC to tip social media posts
    • Amethyst is ~trusted here, and is unlikely to attack the NWC server
  • using a paid service such as ppq.ai that bills the NWC server on-demand
    • ppq.ai is considered an untrusted adversarial entity in this context, so an attack is in-scope

Affected version

  • the NWC plugin was added in version 4.6.0
  • Electrum 4.7.2 contains the fix, all prior versions are affected

First bug (race bypass)

  1. User configures daily_limit_sat=1000.
  2. Malicious NWC client prepares two 1000-sat invoices.
  3. Malicious NWC client sends two pay_invoice requests concurrently on the same connection.
  4. Both may pass budget_allows_spend() before either call to add_to_budget(), resulting in 2000 sat total spend.

Second bug (msat truncation bypass)

  1. User creates an NWC connection with a small limit, e.g. daily_limit_sat=1.
  2. Pay a zero-amount invoice via NWC using amount=1999 (msat).
  3. Budget logic accounts invoice.get_amount_sat() as 1 sat, while spend is 1.999 sat.
  4. Repeating this exceeds intended sat-limit policy.

Relevant code snippets

- Concurrent request task spawning: https://github.com/spesmilo/electrum/blob/ff44d4b4d16d420efe6202634eb1a42292905270/electrum/plugins/nwc/nwcserver.py#L350-L370
- Budget check then payment then budget update (non-atomic): https://github.com/spesmilo/electrum/blob/ff44d4b4d16d420efe6202634eb1a42292905270/electrum/plugins/nwc/nwcserver.py#L835-L853
- Budget allow logic: https://github.com/spesmilo/electrum/blob/ff44d4b4d16d420efe6202634eb1a42292905270/electrum/plugins/nwc/nwcserver.py#L892-L899
- Amount conversion truncates msat->sat (floor): https://github.com/spesmilo/electrum/blob/ff44d4b4d16d420efe6202634eb1a42292905270/electrum/invoices.py#L175-L183

Patches

Electrum 4.7.2 fully fixes these.
The race bypass bug is fixed in: 5222374
The msat truncation is fixed in: 3956bff

Timeline

  • 2026-03-02: private disclosure received
  • 2026-03-03: fixes implemented, reviewed, merged
  • 2026-04-02: version 4.7.2 released that includes the fixes
  • 2026-04-28: public disclosure

Credits

We thank maru1009 for finding and responsibly disclosing these issues to us, nicely written up in an easy to understand way.

Severity

Low

CVE ID

No known CVE

Weaknesses

No CWEs