What changed, and why it matters
This commit adds a single safety check before showing an authentication screen in the Cake Wallet app. It makes sure the screen (called 'context') is still valid and mounted before trying to navigate. Without this check, the app could crash or behave unexpectedly if the user closed or changed screens while authentication was starting. The rest of the change is mostly code formatting and indentation cleanup.
Treat as a routine stability/defensive-coding improvement. No urgent security action required. Reviewers may verify that other Navigator calls in the codebase also use context.mounted guards where asynchronous gaps exist.
Security signals we found
Defensive null/state guard added (context.mounted check)
No change to secret storage, duress PIN handling, or authentication logic
Crash-avoidance / stability improvement rather than vulnerability fix
No references to CVEs, advisories, or security disclosures in commit
Evidence from the diff
The functional change in lib/core/auth_service.dart wraps the Navigator.of(context).pushNamed(Routes.auth, …) call with if (context.mounted) { … }. This guards against calling Navigator on a BuildContext whose widget is no longer in the widget tree, which can throw an assertion error or lead to a crash in Flutter. The remaining diff is whitespace/indentation reformatting and a minor trailing newline removal. No cryptographic, authentication-bypass, or secret-handling logic was changed.
Changed components
lib/core/auth_service.dartAuthentication navigation flowInspect captured patch +43 / −44
diff --git a/lib/core/auth_service.dart b/lib/core/auth_service.dart
index 39fc5307..48719291 100644
--- a/lib/core/auth_service.dart
+++ b/lib/core/auth_service.dart
@@ -96,8 +96,7 @@ class AuthService with Store {
}
// Check for duress pin
- final duressKey =
- generateStoreKeyFor(key: SecretStoreKey.duressPinCodePassword);
+ final duressKey = generateStoreKeyFor(key: SecretStoreKey.duressPinCodePassword);
final encodedDuressPin = await secureStorage.read(key: duressKey);
String? decodedDuressPin;
@@ -110,12 +109,12 @@ class AuthService with Store {
}
if (decodedDuressPin == pin) {
- await _handleDuressLogin(secureStorage, sharedPreferences,
- authenticationStore, appStore, resetService, walletList);
+ await _handleDuressLogin(secureStorage, sharedPreferences, authenticationStore, appStore,
+ resetService, walletList);
navigatorKey.currentState?.pushNamedAndRemoveUntil(
Routes.welcome,
- (route) => false,
+ (route) => false,
);
return false;
@@ -167,52 +166,53 @@ class AuthService with Store {
}
}
- Navigator.of(context).pushNamed(Routes.auth,
- arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) async {
- if (!isAuthenticatedSuccessfully) {
- onAuthSuccess?.call(false);
- return;
- } else {
- if (settingsStore.useTOTP2FA && conditionToDetermineIfToUse2FA) {
- auth.close(
- route: Routes.totpAuthCodePage,
- arguments: TotpAuthArgumentsModel(
- isForSetup: !settingsStore.useTOTP2FA,
- onTotpAuthenticationFinished:
- (bool isAuthenticatedSuccessfully, TotpAuthCodePageState totpAuth) async {
- if (!isAuthenticatedSuccessfully) {
- onAuthSuccess?.call(false);
- return;
- }
- if (onAuthSuccess != null) {
- totpAuth.close().then((value) => onAuthSuccess.call(true));
- } else {
- totpAuth.close(route: route, arguments: arguments);
- }
- },
- ),
- );
+ if (context.mounted) {
+ Navigator.of(context).pushNamed(Routes.auth,
+ arguments: (bool isAuthenticatedSuccessfully, AuthPageState auth) async {
+ if (!isAuthenticatedSuccessfully) {
+ onAuthSuccess?.call(false);
+ return;
} else {
- if (onAuthSuccess != null) {
- auth.close().then((value) => onAuthSuccess.call(true));
+ if (settingsStore.useTOTP2FA && conditionToDetermineIfToUse2FA) {
+ auth.close(
+ route: Routes.totpAuthCodePage,
+ arguments: TotpAuthArgumentsModel(
+ isForSetup: !settingsStore.useTOTP2FA,
+ onTotpAuthenticationFinished:
+ (bool isAuthenticatedSuccessfully, TotpAuthCodePageState totpAuth) async {
+ if (!isAuthenticatedSuccessfully) {
+ onAuthSuccess?.call(false);
+ return;
+ }
+ if (onAuthSuccess != null) {
+ totpAuth.close().then((value) => onAuthSuccess.call(true));
+ } else {
+ totpAuth.close(route: route, arguments: arguments);
+ }
+ },
+ ),
+ );
} else {
- auth.close(route: route, arguments: arguments);
+ if (onAuthSuccess != null) {
+ auth.close().then((value) => onAuthSuccess.call(true));
+ } else {
+ auth.close(route: route, arguments: arguments);
+ }
}
}
- }
- });
+ });
+ }
}
}
-
Future<void> _handleDuressLogin(
- SecureStorage secureStorage,
- SharedPreferences sharedPreferences,
- AuthenticationStore authenticationStore,
- AppStore appStore,
- ResetService resetService,
- List<WalletInfo> wallets,
- ) async {
+ SecureStorage secureStorage,
+ SharedPreferences sharedPreferences,
+ AuthenticationStore authenticationStore,
+ AppStore appStore,
+ ResetService resetService,
+ List<WalletInfo> wallets,
+) async {
printV('[DURESS] START FULL WIPE PROCESS');
// Close wallet instance if opened
@@ -278,4 +278,3 @@ Future<void> _handleDuressLogin(
printV('[DURESS] FULL WIPE COMPLETED');
}
-
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.