What changed, and why it matters
This commit fixes a broken feature in the Monero wallet's setup wizard that restores a wallet by scanning a QR code. The feature had been completely non-functional since a prior redesign because the code that processes the scanned QR code was placed in a JavaScript library that cannot access the wizard's user-interface elements. The patch moves that code into the correct wizard page, updates it to use the current user-interface elements, and safely handles QR codes that contain only an address with no extra key data. This is a straightforward bug fix with no clear security relevance.
Treat as a normal bug-fix commit. No security response is indicated. If reviewing the broader restore flow, consider verifying that scanned secret view/spend keys are handled only in memory and not logged or persisted unexpectedly, but that is outside the scope of this diff.
Security signals we found
No security-relevant signals in the diff or commit message
Fixes a broken user-facing feature (restore from QR code)
Adds null-safety for extra_parameters to prevent crashes on bare-address QR codes
No input validation, cryptographic, or privilege changes
Evidence from the diff
The function updateFromQrCode was defined in js/Wizard.js, a QML .pragma library script. Such scripts run without access to the QML component scope, so references to recoverFromSeedMode, spendKeyLine, viewKeyLine, restoreHeight, addressLine, and cameraUi all failed on first use, causing every QR scan to abort without populating the restore form. The function also referenced pre-redesign items. The patch moves updateFromQrCode into WizardRestoreWallet1.qml, connects it directly to cameraUi.qrcode_decoded, switches the UI to keys mode so the scanned fields are visible, and replaces bare property accesses with a null-safe extra_parameters fallback. The change is a functional repair, not a hardening patch.
Changed components
Monero GUI wallet wizardjs/Wizard.jswizard/WizardRestoreWallet1.qmlQR-code wallet restore flowInspect captured patch +18 / −25
diff --git a/js/Wizard.js b/js/Wizard.js
index f1a56ff..db12034 100644
--- a/js/Wizard.js
+++ b/js/Wizard.js
@@ -1,29 +1,5 @@
.pragma library
-function updateFromQrCode(address, payment_id, amount, tx_description, recipient_name, extra_parameters) {
- // Switch to recover from keys
- recoverFromSeedMode = false
- spendKeyLine.text = ""
- viewKeyLine.text = ""
- restoreHeight.text = ""
-
- if(typeof extra_parameters.secret_view_key != "undefined") {
- viewKeyLine.text = extra_parameters.secret_view_key
- }
- if(typeof extra_parameters.secret_spend_key != "undefined") {
- spendKeyLine.text = extra_parameters.secret_spend_key
- }
- if(typeof extra_parameters.restore_height != "undefined") {
- restoreHeight.text = extra_parameters.restore_height
- }
- addressLine.text = address
-
- cameraUi.qrcode_decoded.disconnect(updateFromQrCode)
-
- // Check if keys are correct
- checkNextButton();
-}
-
function switchPage(next) {
// Android focus workaround
releaseFocus();
diff --git a/wizard/WizardRestoreWallet1.qml b/wizard/WizardRestoreWallet1.qml
index 2ee70bd..29f2c63 100644
--- a/wizard/WizardRestoreWallet1.qml
+++ b/wizard/WizardRestoreWallet1.qml
@@ -60,6 +60,23 @@ Rectangle {
return false;
}
+ function updateFromQrCode(address, payment_id, amount, tx_description, recipient_name, extra_parameters) {
+ // the key fields are only visible in 'keys' mode
+ seedRadioButton.checked = false;
+ keysRadioButton.checked = true;
+ qrRadioButton.checked = false;
+ wizardController.walletRestoreMode = 'keys';
+
+ // extra_parameters is null when a bare address was scanned
+ var params = extra_parameters || {};
+ addressLine.text = address;
+ viewKeyLine.text = typeof params.secret_view_key != "undefined" ? params.secret_view_key : "";
+ spendKeyLine.text = typeof params.secret_spend_key != "undefined" ? params.secret_spend_key : "";
+ restoreHeight.text = typeof params.restore_height != "undefined" ? params.restore_height : "";
+
+ cameraUi.qrcode_decoded.disconnect(updateFromQrCode);
+ }
+
function verifyFromKeys() {
var result = Wizard.restoreWalletCheckViewSpendAddress(
walletManager,
@@ -156,7 +173,7 @@ Rectangle {
keysRadioButton.checked = false;
wizardController.walletRestoreMode = 'qr';
cameraUi.state = "Capture";
- cameraUi.qrcode_decoded.connect(Wizard.updateFromQrCode);
+ cameraUi.qrcode_decoded.connect(updateFromQrCode);
}
}
}
Why this scored 23/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.