Merge pull request #10871 from accumulator/hww_deprecation_bb01_archos
What changed, and why it matters
This commit adds user-facing warning popups that appear when Electrum interacts with two older hardware wallets: the Digital Bitbox (BitBox01) and the Archos Safe-T mini. The message tells users these devices are being deprecated, are no longer supported by their manufacturers, and that users should move their coins to a modern device. It is a notification-only change, not a security fix or vulnerability.
No security action required. Users of BitBox01 or Safe-T mini should follow the deprecation guidance and migrate funds to a supported hardware wallet before future Electrum versions drop compatibility.
Security signals we found
No memory safety, cryptographic, or authorization changes
No bug fixes or vulnerability mitigations present in diff
Adds informational deprecation warnings only
Evidence from the diff
The patch introduces a new show_warning() method across the hardware wallet handler interfaces (cmdline, plugin base, and Qt GUI), wires it to a warning_signal in the Qt handler, and calls it from DigitalBitbox_Client.get_xpub() and SafeTClientMixin.get_xpub(). A global flag ensures the deprecation warning is shown only once per process. The actual xpub derivation logic is unchanged.
Changed components
electrum/hw_wallet/cmdline.pyelectrum/hw_wallet/plugin.pyelectrum/hw_wallet/qt.pyelectrum/plugins/digitalbitbox/digitalbitbox.pyelectrum/plugins/safe_t/clientbase.pyInspect captured patch +57 / −11
### electrum/hw_wallet/cmdline.py
@@ -67,6 +67,9 @@ def stop(self):
def show_message(self, msg, on_cancel=None):
print_stderr(msg)
+ def show_warning(self, msg, blocking=False):
+ print_stderr(msg)
+
def show_error(self, msg, blocking=False):
print_stderr(msg)
### electrum/hw_wallet/plugin.py
@@ -334,6 +334,9 @@ def yes_no_question(self, msg: str) -> bool:
def show_message(self, msg: str, on_cancel=None) -> None:
raise NotImplementedError()
+ def show_warning(self, msg: str, blocking: bool = False) -> None:
+ raise NotImplementedError()
+
def show_error(self, msg: str, blocking: bool = False) -> None:
raise NotImplementedError()
### electrum/hw_wallet/qt.py
@@ -62,6 +62,7 @@ class QtHandlerBase(HardwareHandlerBase, QObject, Logger):
passphrase_signal = pyqtSignal(object, object)
message_signal = pyqtSignal(object, object)
+ warning_signal = pyqtSignal(object, object)
error_signal = pyqtSignal(object, object)
word_signal = pyqtSignal(object)
clear_signal = pyqtSignal()
@@ -75,6 +76,7 @@ def __init__(self, win: Union['ElectrumWindow', 'QENewWalletWizard'], device: st
assert win.gui_thread == threading.current_thread(), 'must be called from GUI thread'
self.clear_signal.connect(self.clear_dialog)
self.error_signal.connect(self.error_dialog)
+ self.warning_signal.connect(self.warning_dialog)
self.message_signal.connect(self.message_dialog)
self.passphrase_signal.connect(self.passphrase_dialog)
self.word_signal.connect(self.word_dialog)
@@ -116,6 +118,12 @@ def yes_no_question(self, msg):
def show_message(self, msg, on_cancel=None):
self.message_signal.emit(msg, on_cancel)
+ def show_warning(self, msg, blocking=False):
+ self.done.clear()
+ self.warning_signal.emit(msg, blocking)
+ if blocking:
+ self.done.wait()
+
def show_error(self, msg, blocking=False):
self.done.clear()
self.error_signal.emit(msg, blocking)
@@ -201,6 +209,11 @@ def message_dialog(self, msg, on_cancel=None):
vbox.addLayout(Buttons(CancelButton(dialog)))
dialog.show()
+ def warning_dialog(self, msg, blocking):
+ self.win.show_warning(msg, parent=self.top_level_window())
+ if blocking:
+ self.done.set()
+
def error_dialog(self, msg, blocking):
self.win.show_error(msg, parent=self.top_level_window())
if blocking:
### electrum/plugins/digitalbitbox/digitalbitbox.py
@@ -74,7 +74,7 @@ def derive_keys(x):
ENCRYPTION_PRIVKEY_KEY = 'encryptionprivkey'
CHANNEL_ID_KEY = 'comserverchannelid'
-
+DEPRECATION_WARNING_SHOWN = False
class DigitalBitbox_Client(HardwareClientBase):
def __init__(self, plugin, hidDevice):
@@ -126,18 +126,30 @@ def get_xpub(self, bip32_path, xtype):
raise UserFacingException(_('This device does not reveal xpubs corresponding to non-hardened paths'))
reply = self._get_xpub(bip32_path)
- if reply:
- xpub = reply['xpub']
- # Change type of xpub to the requested type. The firmware
- # only ever returns the mainnet standard type, but it is agnostic
- # to the type when signing.
- if xtype != 'standard' or constants.net.TESTNET:
- node = BIP32Node.from_xkey(xpub, net=constants.BitcoinMainnet)
- xpub = node._replace(xtype=xtype).to_xpub()
- return xpub
- else:
+ if not reply:
raise Exception('no reply')
+ xpub = reply['xpub']
+ # Change type of xpub to the requested type. The firmware
+ # only ever returns the mainnet standard type, but it is agnostic
+ # to the type when signing.
+ if xtype != 'standard' or constants.net.TESTNET:
+ node = BIP32Node.from_xkey(xpub, net=constants.BitcoinMainnet)
+ xpub = node._replace(xtype=xtype).to_xpub()
+
+ deprecation_warning = (
+ "DigitalBitbox (BitBox01) is being deprecated.\n\nIt is no longer supported by the manufacturer.\n"
+ "Future versions of Electrum will no longer be compatible with it.\n\n"
+ "You should move your coins and migrate to a modern hardware device.")
+ _logger.warning(deprecation_warning.replace("\n", " "))
+
+ global DEPRECATION_WARNING_SHOWN
+ if self.handler and not DEPRECATION_WARNING_SHOWN:
+ DEPRECATION_WARNING_SHOWN = True
+ self.handler.show_warning(deprecation_warning, blocking=True)
+
+ return xpub
+
def get_soft_device_id(self):
return None
### electrum/plugins/safe_t/clientbase.py
@@ -13,6 +13,9 @@
from electrum.hw_wallet.plugin import HardwareClientBase, HardwareHandlerBase
+DEPRECATION_WARNING_SHOWN = False
+
+
class GuiMixin(object):
# Requires: self.proto, self.device
handler: Optional[HardwareHandlerBase]
@@ -175,6 +178,18 @@ def get_xpub(self, bip32_path, xtype):
address_n = self.expand_path(bip32_path)
creating = False
node = self.get_public_node(address_n, creating).node
+
+ deprecation_warning = (
+ "Archos Safe-T mini is being deprecated.\n\nIt is no longer supported by the manufacturer.\n"
+ "Future versions of Electrum will no longer be compatible with it.\n\n"
+ "You should move your coins and migrate to a modern hardware device.")
+ self.logger.warning(deprecation_warning.replace("\n", " "))
+
+ global DEPRECATION_WARNING_SHOWN
+ if self.handler and not DEPRECATION_WARNING_SHOWN:
+ DEPRECATION_WARNING_SHOWN = True
+ self.handler.show_warning(deprecation_warning, blocking=True)
+
return BIP32Node(xtype=xtype,
eckey=ecc.ECPubkey(node.public_key),
chaincode=node.chain_code,Why this scored 19/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.