WizardController: set password for temp wallet
What changed, and why it matters
This change fixes a likely security issue in the Monero GUI wallet setup wizard. Previously, temporary wallets created during the setup process were protected by an empty password (""). The patch generates a strong random password for these temporary wallets instead. An empty password on a temporary wallet file could let another program or user on the same computer open the wallet while it exists, even though the file is meant to be short-lived.
Users should upgrade to a Monero GUI release containing this commit. Developers should verify that all other temporary wallet creation paths also use non-empty passwords and that the generated password is not logged or persisted.
Security signals we found
Empty password replaced with cryptographically generated random password for wallet creation
New C++ helper uses QRandomGenerator::system() and base64url encoding for password generation
Change applies to temporary wallet files used during the wizard setup flow
No explicit CVE or security advisory referenced in commit or supplied materials
Evidence from the diff
The commit adds a randomPassword() helper to OSHelper using QRandomGenerator::system() and exposes it to QML. It then replaces two empty-string password arguments in WizardController.qml: one for walletManager.createWallet() and one for walletManager.createWalletFromDeviceAsync(), both operating on temporary wallet files. The change indicates the prior empty-password behavior was insecure for temporary wallets, because the wallet file on disk could be accessed without authentication during the wizard flow. The patch is a hardening/fix rather than a feature, but the commit message does not explicitly label it as a security fix.
Changed components
wizard/WizardController.qmlsrc/main/oshelper.cppsrc/main/oshelper.hInspect captured patch +17 / −2
diff --git a/src/main/oshelper.cpp b/src/main/oshelper.cpp
index d44fc8c..2ca0e40 100644
--- a/src/main/oshelper.cpp
+++ b/src/main/oshelper.cpp
@@ -43,6 +43,8 @@
#include <QFileInfo>
#include <QString>
#include <QUrl>
+#include <QByteArray>
+#include <QRandomGenerator>
#ifdef Q_OS_MAC
#include "qt/macoshelper.h"
#endif
@@ -246,6 +248,18 @@ QString OSHelper::temporaryPath() const
return QDir::tempPath();
}
+QString OSHelper::randomPassword(int numBytes) const
+{
+ numBytes = qBound(16, numBytes, 128);
+
+ QByteArray buf(numBytes, Qt::Uninitialized);
+ auto *rng = QRandomGenerator::system();
+ for (int i = 0; i < numBytes; ++i)
+ buf[i] = char(rng->generate() & 0xFF);
+
+ return QString::fromLatin1(buf.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals));
+}
+
bool OSHelper::installed() const
{
#ifdef Q_OS_WIN
diff --git a/src/main/oshelper.h b/src/main/oshelper.h
index 4242cc0..dc3058d 100644
--- a/src/main/oshelper.h
+++ b/src/main/oshelper.h
@@ -51,6 +51,7 @@ public:
Q_INVOKABLE QString openSaveFileDialog(const QString &title, const QString &folder, const QString &filename) const;
Q_INVOKABLE QString temporaryFilename() const;
Q_INVOKABLE QString temporaryPath() const;
+ Q_INVOKABLE QString randomPassword(int numBytes = 32) const;
Q_INVOKABLE bool removeTemporaryWallet(const QString &walletName) const;
Q_INVOKABLE bool isCapsLock() const;
Q_INVOKABLE quint8 getNetworkTypeFromFile(const QString &keysPath) const;
diff --git a/wizard/WizardController.qml b/wizard/WizardController.qml
index 1bc5ca9..eb72709 100644
--- a/wizard/WizardController.qml
+++ b/wizard/WizardController.qml
@@ -345,7 +345,7 @@ Rectangle {
console.log("Creating temporary wallet", tmp_wallet_filename)
var nettype = appWindow.persistentSettings.nettype;
var kdfRounds = appWindow.persistentSettings.kdfRounds;
- var wallet = walletManager.createWallet(tmp_wallet_filename, "", persistentSettings.language_wallet, nettype, kdfRounds)
+ var wallet = walletManager.createWallet(tmp_wallet_filename, oshelper.randomPassword(), persistentSettings.language_wallet, nettype, kdfRounds)
wizardController.walletOptionsSeed = wallet.seed
@@ -479,7 +479,7 @@ Rectangle {
var deviceName = wizardController.walletOptionsDeviceName;
connect();
- walletManager.createWalletFromDeviceAsync(tmpWalletFilename, "", nettype, deviceName, restoreHeight, subaddressLookahead, kdfRounds);
+ walletManager.createWalletFromDeviceAsync(tmpWalletFilename, oshelper.randomPassword(), nettype, deviceName, restoreHeight, subaddressLookahead, kdfRounds);
creatingWalletDeviceSplash();
}
Why this scored 61/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.