Skip to content

External Plugin authorization bypass: local code execution

Moderate
SomberNight published GHSA-vw94-r84p-66qf Apr 28, 2026

Package

electrum

Affected versions

4.6.0<=x<4.7.2

Patched versions

4.7.2

Description

Impact

A rogue program already running on the victim's machine, which has filesystem write access to the Electrum data directory, can place arbitrary plugin code in the plugins/ folder, mark that plugin "enabled" by writing into the config file, and hence get Electrum to execute arbitrary code inside the main python process.

Context

  • Electrum has support for external and internal (built-in) plugins.
  • To load external plugins (.zip files),
    • first, one-time, the user needs to set up a "plugin password" (independent of the wallet passwords)
      • the user is instructed to store a public key string derived from the plugin password in a file owned by root (world-readable but not writable)
    • then to authorize and enable an external plugin, the user is prompted for their plugin password, checked against the stored pubkey
      • if matches, the plugin privkey ecdsa-signs the hash of the plugin zip-file, and the hash is stored in the config file (which is 0600, owned by the user, writeable by the python process).
    • on application start, zip-file plugins get loaded and are able to run code if there is a valid signature for them in the config file
  • The threat model goal is that a rogue non-root process on a compromised machine should not be able to get code execution inside the main Electrum python process.

Affected version

  • the external plugin system was introduced in Electrum 4.6.0, already vulnerable to this issue
  • Electrum 4.7.2 contains the fix, all prior versions are affected

The bug

  • Prior to the introduction of the external plugin system, plugins had their metadata (e.g. full name, description, list of supported GUIs, declared hardware device support) stored as code in their __init__.py module.
    • This meant plugin code would have to be executed to even show a GUI dialog asking the user if they want to enable a plugin.
    • To be able to describe an external plugin in the GUI to the user before letting it run code, this metadata was moved from __init_.py to a manifest.json, which should be safe to parse.
  • __init__.py was still kept: it is used by plugins that register CLI commands. CLI commands have a name, arguments, a docstring, etc, which we did not want to duplicate in manifest.json - it can just be parsed out at runtime from .py code.
  • So plugins are loaded in two steps:
    • step 1 [0]: __init__.py is loaded,
    • step 2 [1]: the full plugin is loaded
  • The vulnerability is that while step 2 validated whether the zip file hash is signed by the plugin password, step 1 only checked if the plugin is marked as "enabled" in the config file - without checking the corresponding signature.

Relevant code snippets

[0] https://github.com/spesmilo/electrum/blob/2a5b1b22beeedec83e30b2f5c2b22915dc5b6b06/electrum/plugin.py#L590
[1] https://github.com/spesmilo/electrum/blob/2a5b1b22beeedec83e30b2f5c2b22915dc5b6b06/electrum/plugin.py#L611

Patches

Electrum 4.7.2 contains the fix: 032dfcf
(cherry-picked in fd7164d)

Timeline

  • 2026-03-26: private disclosure received
  • 2026-03-26: fixes implemented, reviewed, merged
  • 2026-04-02: a bug bounty of 1000 eur in btc was paid to the reporter for responsible disclosure
  • 2026-04-02: version 4.7.2 released with fix included
  • 2026-04-28: public disclosure

Credits

We thank Kevil_G for finding and responsibly disclosing this issue to us.

Severity

Moderate

CVE ID

No known CVE

Weaknesses

No CWEs