fix: give a wallet whose password is lost a way out, and say the password cannot be reset (closes #312)
A user who forgot their password but held their recovery phrase was permanently locked out: deletion was password-gated and re-importing the phrase was refused as a duplicate. Their only escape was destroying extension storage through browser internals, taking every other wallet with it. DeleteWallet gains an "I have lost my password" route that destroys the stored secret after the wallet's name is typed back. No password gate was added: requiring one to discard a secret protects nothing, since an attacker who wants destruction can uninstall the extension, and the only person it stops is the legitimate user who lost it. The screen is excluded from RESTORABLE_VIEWS and registers an onViewLeave cleanup. Deletion was chosen over re-import because a key wallet is duplicate-checked by address rather than xpub, so an xpub-only relaxation would leave that user still wedged; because re-import makes the user retype their recovery phrase into a live popup merely to change a password; and because it reaches no end state that delete-then-import plus scanForAddresses() does not. The attacker argument did not decide it — re-import clears the "no worse than the phrase alone" bar. All three AddWallet password hints now state the password cannot be recovered or reset and name that mode's only backup, the xprv mode correctly claiming no recovery phrase. deleteAddress.js no longer tells the user that deleting a wallet asks for a password, which this change made false. The typed confirmation collapses internal whitespace on both sides: a wallet renamed with two spaces displays with one, so the string a user could see and type could never match, making the confirmation untypable on the one screen whose purpose is un-wedging a stuck user. Measured, not reasoned, after review found the first reserve twice too large and pushing the Import button below the fold: #btn-add-wallet-confirm bottom 628.13 -> 580.13 at 360x600, scrollHeight 636 -> 600, hint box 48px identical across all three tabs and on re-entry. make check 40 suites / 828 tests, test-e2e 55/55, test-e2e-firefox 8/8.
This commit was merged in pull request #334.
This commit is contained in:
@@ -153,12 +153,28 @@
|
||||
<!-- Shared password fields -->
|
||||
<div class="mb-2" id="add-wallet-password-section">
|
||||
<label class="block mb-1">Choose a password</label>
|
||||
<!-- The hint is swapped in place when the import tab
|
||||
changes, and it sits directly above the password
|
||||
fields, so a wording that wraps to a different
|
||||
number of lines would move them under the pointer.
|
||||
Two things stop that: the three wordings in
|
||||
PASSWORD_HINTS are kept within a couple of
|
||||
characters of each other in length, and this floor
|
||||
matches what each of them needs. All three measure
|
||||
48px -- 3 lines at the 16px line height, at the
|
||||
368px width this box has in the 396px popup body.
|
||||
Do not raise it: the reserve is unused height on
|
||||
every tab, and at 6rem it pushed
|
||||
#btn-add-wallet-confirm to bottom=628px in a 600px
|
||||
viewport, below the fold. -->
|
||||
<p
|
||||
class="text-xs text-muted mb-1"
|
||||
class="text-xs text-muted mb-1 min-h-[3rem]"
|
||||
id="add-wallet-password-hint"
|
||||
>
|
||||
This password encrypts your recovery phrase on this
|
||||
device. You will need it to send funds.
|
||||
device. You will need it to send funds. It cannot be
|
||||
recovered or reset, so keep your recovery phrase written
|
||||
down: it is the only backup of this wallet.
|
||||
</p>
|
||||
<input
|
||||
type="password"
|
||||
@@ -1140,6 +1156,71 @@
|
||||
>
|
||||
Confirm Delete
|
||||
</button>
|
||||
<p class="text-xs mt-3">
|
||||
<span
|
||||
id="btn-delete-wallet-lost-password"
|
||||
class="underline decoration-dashed cursor-pointer"
|
||||
>I have lost my password</span
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- ============ DELETE WALLET WITHOUT THE PASSWORD ============ -->
|
||||
<div id="view-delete-wallet-lost-password" class="view hidden">
|
||||
<button
|
||||
id="btn-delete-wallet-lost-back"
|
||||
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer mb-2"
|
||||
>
|
||||
< Back
|
||||
</button>
|
||||
<h2 class="font-bold mb-3">Delete Wallet Without a Password</h2>
|
||||
<p class="text-xs mb-2">
|
||||
Your password cannot be recovered or reset, so there is no
|
||||
way to unlock
|
||||
<strong id="delete-wallet-lost-name"></strong> again. You
|
||||
can still delete it, and no password is needed to do that.
|
||||
</p>
|
||||
<p class="text-xs mb-2">
|
||||
Deleting it erases the copy of its key that is stored on
|
||||
this device. Nothing on the blockchain changes, and the
|
||||
money at its addresses is not moved or destroyed.
|
||||
</p>
|
||||
<p class="text-xs mb-2">
|
||||
If you have the recovery phrase for this wallet written
|
||||
down, add the wallet again afterwards with a new password
|
||||
and you will have it back.
|
||||
<strong
|
||||
>If you do not have it written down, deleting this
|
||||
wallet means losing everything it holds,
|
||||
forever.</strong
|
||||
>
|
||||
</p>
|
||||
<p class="text-xs mb-3">Your other wallets are not touched.</p>
|
||||
<p class="text-xs mb-1">
|
||||
To confirm, type the name of the wallet (<strong
|
||||
id="delete-wallet-lost-name-echo"
|
||||
></strong
|
||||
>) below.
|
||||
</p>
|
||||
<div class="mb-2">
|
||||
<input
|
||||
type="text"
|
||||
id="delete-wallet-lost-name-input"
|
||||
class="border border-border p-1 w-full font-mono text-sm bg-bg text-fg"
|
||||
placeholder="Type the wallet name"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
id="delete-wallet-lost-flash"
|
||||
class="text-xs text-red-500 mb-2 min-h-[1.25rem]"
|
||||
style="visibility: hidden"
|
||||
></div>
|
||||
<button
|
||||
id="btn-delete-wallet-lost-confirm"
|
||||
class="border border-border text-red-500 px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
||||
>
|
||||
Delete This Wallet Forever
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- ============ DELETE ADDRESS CONFIRM ============ -->
|
||||
|
||||
Reference in New Issue
Block a user