await wallet name check [skip ci]
What changed, and why it matters
This commit fixes a bug where the app did not wait for a check that a wallet name already exists before continuing to create or restore a wallet. Because the check was not awaited, the app could proceed before knowing the result, potentially allowing a duplicate wallet to be created or overwriting an existing one. The fix simply adds 'await' so the check completes first.
Review whether any duplicate wallets were created or existing wallets were overwritten due to this bug, and consider adding tests that verify the existence check is awaited before filesystem operations begin.
Security signals we found
Race condition / missing await in security-critical validation
Duplicate-name guard bypass in wallet creation and restore flows
Potential wallet overwrite or restoration into existing wallet directory
Evidence from the diff
The patch adds ‘await’ to four calls to checkIfExists() in wallet creation/restore paths. Previously these calls returned a Future that was never awaited, so execution continued concurrently. If the existence check is asynchronous (e.g., filesystem or database lookup), the subsequent wallet directory creation and restoration could race ahead of the check, bypassing the duplicate-name guard. The fix ensures the guard completes before any destructive filesystem operations.
Changed components
lib/core/wallet_creation_service.dartlib/view_model/wallet_creation_vm.dartInspect captured patch +4 / −4
diff --git a/lib/core/wallet_creation_service.dart b/lib/core/wallet_creation_service.dart
index 7f09e7bf..51f1b288 100644
--- a/lib/core/wallet_creation_service.dart
+++ b/lib/core/wallet_creation_service.dart
@@ -97,7 +97,7 @@ class WalletCreationService {
}
Future<WalletBase> restoreFromKeys(WalletCredentials credentials, {bool? isTestnet}) async {
- checkIfExists(credentials.name);
+ await checkIfExists(credentials.name);
if (credentials.password == null) {
credentials.password = generateWalletPassword();
@@ -116,7 +116,7 @@ class WalletCreationService {
}
Future<WalletBase> restoreFromSeed(WalletCredentials credentials, {bool? isTestnet}) async {
- checkIfExists(credentials.name);
+ await checkIfExists(credentials.name);
if (credentials.password == null) {
credentials.password = generateWalletPassword();
@@ -135,7 +135,7 @@ class WalletCreationService {
}
Future<WalletBase> restoreFromHardwareWallet(WalletCredentials credentials) async {
- checkIfExists(credentials.name);
+ await checkIfExists(credentials.name);
final password = generateWalletPassword();
credentials.password = password;
await keyService.saveWalletPassword(password: password, walletName: credentials.name);
diff --git a/lib/view_model/wallet_creation_vm.dart b/lib/view_model/wallet_creation_vm.dart
index 60918051..fdc91200 100644
--- a/lib/view_model/wallet_creation_vm.dart
+++ b/lib/view_model/wallet_creation_vm.dart
@@ -95,7 +95,7 @@ abstract class WalletCreationVMBase with Store {
throw Exception(S.current.repeated_password_is_incorrect);
}
- walletCreationService.checkIfExists(name);
+ await walletCreationService.checkIfExists(name);
final dirPath = await pathForWalletDir(name: name, type: type);
final path = await pathForWallet(name: name, type: type);
Why this scored 49/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.