MetaMask / MetaMask/metamask-mobile

[Bug]: Seedless (Sign in with Apple) wallet permanently rate-limited after reinstall: lock re-arms to 24h on every attempt, password never evaluated, support cannot reset

Open
#36,193 2 comments 0 reactions 0 assignees View on GitHub
external-contributor INVALID-ISSUE-TEMPLATE Sev0-urgent ta-needs-engineer-escalation ta-security-review ta-triaged team-auth
Dominant language
TypeScript
Stars
3k
Forks
1.7k
Avg merge
1d 14h
Merged PRs (30d)
669

Description

### Describe the bug

A seedless wallet created with **Sign in with Apple** on MetaMask iOS cannot be unlocked after the app was deleted and reinstalled. Every unlock returns **"Too many attempts. Try again in 23:59:xx"**. The **incorrect-password error has never appeared once**, from the very first attempt after the reinstall. The password is the Apple-generated one saved in iCloud Keychain and has never changed; it unlocked the wallet daily for a week before the reinstall.

The lock **re-arms to a full 24 hours on every attempt** and the guess counter **never decays**. Controlled test: zero attempts for 2 days, then 3 days, then about 4 days; the first attempt after each wait returned a fresh 24:00 lock. Zero attempts since August 23, so the account is in whatever state the nodes hold right now.

MetaMask Support (tickets #121135651 and #127213997) has stated in writing that support cannot read or reset the per-account rate-limit counters on the TOPRF key-share nodes and has no admin override. The Builder Hub (topic 3504) says it is out of scope for the developer forum. So there is currently **no path for an affected user to regain access**, even with the correct credentials.

Client-side observation, verified in the shipped `@metamask/toprf-secure-backup@1.1.0`: `validateSeed` in `dist/toprfEvalRequest.mjs` throws `rateLimitExceeded` from `checkRateLimitErrors` **before** `filterCompletedRequests` and before the `TOPRF_EVAL_THRESHOLD = 3` check, so a single rate-limited node aborts a recovery that three healthy nodes could serve, and the UI shows only the maximum lock across nodes. Whether one node or all five are locked on this account is not observable from the client.

A fuller write-up with account identifiers was sent to bugbounty@consensys.net on 2026-09-14 (UTC). Identifiers are deliberately not posted here; happy to share them privately with anyone on the onboarding team.

### Expected behavior

Either the correct password is evaluated once the stated cooldown expires, or the counter decays with time as the "try again in X" message implies. A lock that re-arms on every attempt and never decays is a permanent lockout.

### Screenshots/Recordings

Not attached. Producing a new screenshot requires a new attempt, which re-arms the 24h lock; I am avoiding that until someone can read the node-side state.

### Steps to reproduce

1. Create a wallet on MetaMask iOS with Sign in with Apple (this one: July 23, 2026), accepting Apple's suggested strong password (saved to iCloud Keychain).
2. Use it normally for a week (Face ID unlock).
3. Delete the app (July 30). Reinstall from the App Store (July 31). Choose "I have an existing wallet", Sign in with Apple.
4. Apple sign-in succeeds and the wallet is found. At the unlock step, enter the saved password (AutoFill).
5. Observe only "Too many attempts" with escalating waits (3 min → 10 → 30 → 45 → 24 h). Never "incorrect password".
6. Wait 2, 3, 4 days with zero attempts. First attempt after each wait: fresh 24:00 lock.
7. Same result on the Chrome extension (13.44.0.0), whose state shows `firstTimeFlowType: socialImport`, no local vault, `completedOnboarding: false` — the unlock screen is issuing the network recovery call.

### Error messages or log output

UI string only: `Too many attempts. Try again in 23:59:xx` (i18n `unlockPageTooManyFailedAttempts`, thrown as `SeedlessOnboardingController - Too many login attempts`). No raw payload captured; capturing one needs a new attempt.

### Where was this bug found?

Live version (from official store)

### Version

App Store build current on July 31, 2026 at the reinstall (8.4.x era); exact build number not recorded. The lock persists on today's 8.10.1 as far as can be told without attempting.

### Build number

Not recorded

### Build type

_No response_

### Device

iPhone, iOS 26.5.2

### Operating system

iOS

### Additional context

- Support conversation history: chat Aug 1 (agent Nyx), ticket #121135651 Aug 3–16 (agents Kirk/Sam, resolved "nothing we can do"), ticket #127213997 Aug 23 (resolved Aug 24 with no reply).
- Builder Hub topic: https://builder.metamask.io/t/3504
- Related: #27384 was a different seedless permanent-lockout (local vault format); this one is node-side.
- Funds are in the wallet's Bitcoin account. I will never share the password or a recovery phrase, and I am not asking for either to be recovered; I am asking for the node-side rate-limit state to be inspected and, if it cannot decay, reset.

Contributor guide

Open the contributing guide

Research direction

The client observation is in @metamask/toprf-secure-backup@1.1.0, specifically dist/toprfEvalRequest.mjs: validateSeed, checkRateLimitErrors, filterCompletedRequests, and TOPRF_EVAL_THRESHOLD = 3. Start by tracing that recovery path and determining the per-account state on the TOPRF key-share nodes. Done means the correct password can be evaluated after cooldown, or counters decay or reset without a permanent lockout; account identifiers should be shared privately.

Written by the indexing model from the issue text.

Assessment

Tech stack
ios, react-native, typescript
Domain
authentication, backend-api-design, security
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.