Skip to content

feat: add optional data wipe after failed password attempts#1794

Open
goncalosamp27 wants to merge 9 commits intobeemdevelopment:masterfrom
skrtstsk:proposal/1749
Open

feat: add optional data wipe after failed password attempts#1794
goncalosamp27 wants to merge 9 commits intobeemdevelopment:masterfrom
skrtstsk:proposal/1749

Conversation

@goncalosamp27
Copy link
Copy Markdown

This PR implements the optional failed-attempt protection proposed in #1749.

It adds a Security setting that allows users to enable automatic vault wiping after a configurable number of failed unlock attempts. The feature is disabled by default. Failed attempts are persisted locally, and after several consecutive failures the authentication screen applies a progressive temporary lockout with a visible countdown.

When data wiping is enabled and the configured limit is reached, the implementation reuses the existing vault deletion functionality to remove the vault file, lock the vault, and exit the app. One attempt before the limit, the user is shown a warning dialog explaining that another failed attempt will erase the vault data.

Fixes #1749

Please let me know if anything needs to be changed in this PR.

Copilot AI review requested due to automatic review settings May 4, 2026 22:26
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an optional security feature to progressively lock out users after consecutive failed unlock attempts and (optionally) wipe the vault after a configurable limit, with settings exposed under Security preferences.

Changes:

  • Added Security settings for enabling data wiping and configuring the maximum failed unlock attempts.
  • Implemented persisted failed-attempt tracking, progressive lockout with countdown UI, and a “final attempt” warning dialog.
  • Reused existing vault deletion/lock+exit flow to wipe the vault when the configured limit is reached.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
app/src/main/res/xml/preferences_security.xml Adds new Security preferences (toggle + max-attempts entry).
app/src/main/res/values/strings.xml Adds strings for the new preferences, lockout message, warning dialog, and empty-password validation.
app/src/main/res/layout/activity_auth.xml Adds a lockout countdown message TextView to the auth screen.
app/src/main/res/drawable/ic_warning_24.xml Adds a warning icon used by the “final attempt” dialog.
app/src/main/java/com/beemdevelopment/aegis/ui/fragments/preferences/SecurityPreferencesFragment.java Wires the new preferences to a number picker dialog and persists the selection.
app/src/main/java/com/beemdevelopment/aegis/ui/dialogs/Dialogs.java Adds a number picker dialog for selecting max failed attempts.
app/src/main/java/com/beemdevelopment/aegis/ui/AuthActivity.java Implements failed-attempt persistence, lockout logic/countdown, final-attempt warning, and wipe+exit behavior.
app/src/main/java/com/beemdevelopment/aegis/Preferences.java Adds preference accessors for enabling wipe + max failed attempts.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

private Button _decryptButton;

private int _failedUnlockAttempts;
private TextView _textFailedAttempts;
char[] password = EditTextHelper.getEditTextChars(_textPassword);

if (password.length == 0) {
Toast.makeText(AuthActivity.this, getString(R.string.error_empty_password), Toast.LENGTH_SHORT).show(); return;
Comment on lines +476 to +483
long minutes = totalSeconds / 60;
long seconds = totalSeconds % 60;

@SuppressLint("DefaultLocale") String timeFormatted = String.format("%02d:%02d", minutes, seconds);

_textLockout.setText(
getString(R.string.lockout_message, _failedUnlockAttempts, timeFormatted)
);
Comment on lines +568 to +589
dialog.setOnShowListener(d -> {
Button positiveButton = dialog.getButton(androidx.appcompat.app.AlertDialog.BUTTON_POSITIVE);
positiveButton.setEnabled(false);

new CountDownTimer(delayMillis, 1000) {
@Override
public void onTick(long millisUntilFinished) {
long secondsLeft = (millisUntilFinished + 999) / 1000;
positiveButton.setText(getString(R.string.ok_with_timer, secondsLeft));
}

@Override
public void onFinish() {
positiveButton.setText(getString(android.R.string.ok));
positiveButton.setEnabled(true);
positiveButton.setOnClickListener(v -> {
dialog.dismiss();
selectPassword();
});
}
}.start();
});
NumberPicker numberPicker = view.findViewById(R.id.numberPicker);
numberPicker.setMinValue(1);
numberPicker.setMaxValue(100);
numberPicker.setValue(currentValue);
Comment on lines +488 to +494
public int getMaxFailedAttemptsBeforeWipe() {
return _prefs.getInt("pref_max_failed_attempts", 10);
}

public void setMaxFailedAttemptsBeforeWipe(int attempts) {
_prefs.edit().putInt("pref_max_failed_attempts", attempts).apply();
}
});

_dataWipingPreference = requirePreference("pref_enable_data_wiping");
_maxFailedAttemptsPreference = requirePreference("pref_max_failed_attempts");
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:textColor="@android:color/holo_red_dark"
Comment on lines +1 to +3
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">

<path android:fillColor="@android:color/white" android:pathData="M12,5.99L19.53,19H4.47L12,5.99M12,2L1,21h22L12,2L12,2z"/>
<string name="pref_enable_data_wiping_title">Enable data wiping</string>
<string name="pref_enable_data_wiping_summary">Erase vault data after several successive failed login attempts</string>
<string name="pref_max_failed_attempts_title">Maximum failed login attempts</string>
<string name="pref_max_failed_attempts_summary">%1$d attempts</string>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature Request: Data wipe after multiple failed password attempts

2 participants