fix(python/trezorctl): default to advanced recovery for <24 words on legacy
What changed, and why it matters
This commit changes the Trezor command-line tool so that when a user restores a wallet with fewer than 24 words on older (legacy) Trezor devices, it automatically uses the 'advanced/matrix' recovery method instead of the default 'scrambled words' method. The scrambled method is disabled for shorter mnemonics on legacy firmware, so without this change the recovery command could fail or behave unexpectedly. It is a usability/compatibility fix rather than a fix for a vulnerability that lets an attacker steal funds.
No security action required. Treat as a normal client compatibility/UX fix. Users relying on scripted recovery should verify the new default matches their intended workflow.
Security signals we found
Behavioral default change in recovery workflow
Legacy device compatibility adjustment
No cryptographic, authentication, or authorization changes
No input validation, buffer handling, or secret handling changes
Evidence from the diff
In python/src/trezorlib/cli/device.py, the recover command’s --type option default is changed from scrambled to None. When no input method is explicitly chosen, the code now selects ScrambledWords for 24-word mnemonics and Matrix (advanced recovery) for anything shorter. This aligns the CLI default with legacy device behavior where ScrambledWords is disabled for non-24-word seeds. The change only affects the Python client-side default selection and the input callback used during recovery.
Changed components
python/src/trezorlib/cli/device.pyTrezor CLI recovery command (`trezorctl device recover`)Legacy Trezor device recovery interactionInspect captured patch +11 / −3
diff --git a/python/.changelog.d/6525.changed b/python/.changelog.d/6525.changed
new file mode 100644
index 00000000..e25370c8
--- /dev/null
+++ b/python/.changelog.d/6525.changed
@@ -0,0 +1 @@
+Default to advanced recovery for mnemonics shorter than 24 words on legacy.
diff --git a/python/src/trezorlib/cli/device.py b/python/src/trezorlib/cli/device.py
index ed0cbb39..bd51d883 100644
--- a/python/src/trezorlib/cli/device.py
+++ b/python/src/trezorlib/cli/device.py
@@ -169,7 +169,7 @@ def load(
"-t",
"--type",
type=ChoiceType(RECOVERY_DEVICE_INPUT_METHOD),
- default="scrambled",
+ default=None,
)
@click.option("-d", "--dry-run", is_flag=True)
@click.option("-b", "--unlock-repeated-backup", is_flag=True)
@@ -182,11 +182,18 @@ def recover(
passphrase_protection: bool,
label: str | None,
u2f_counter: int,
- input_method: messages.RecoveryDeviceInputMethod,
+ input_method: messages.RecoveryDeviceInputMethod | None,
dry_run: bool,
unlock_repeated_backup: bool,
) -> None:
"""Start safe recovery workflow."""
+ word_count = int(words)
+ if input_method is None:
+ input_method = messages.RecoveryDeviceInputMethod.ScrambledWords
+ if word_count < 24:
+ # `ScrambledWords` is disabled by default for shorter mnemonics.
+ input_method = messages.RecoveryDeviceInputMethod.Matrix
+
if input_method == messages.RecoveryDeviceInputMethod.ScrambledWords:
input_callback = ui.mnemonic_words(expand)
else:
@@ -204,7 +211,7 @@ def recover(
device.recover(
session,
- word_count=int(words),
+ word_count=word_count,
passphrase_protection=passphrase_protection,
pin_protection=pin_protection,
label=label,
Why this scored 21/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.