Limit OTP guesses to stop brute-force enumeration
Aliases: OTP rate limit · online guessing · one-time code lockout
What it is
Short numeric codes have a small space; unlimited submits can walk it. An attempt limit means a given code, for a given sign-in challenge, may be checked only a bounded number of times within its life; beyond that the code is void and a new send is required, rather than leaving the field submittable. This entry is about the guessing window. It is not about paste into the box, and it is not magic-link single-use—link entropy is usually high, and enumeration is not the main threat there.
Why it happens
Six decimal digits are a million possibilities. If online checks can run many times per second, exhausting the space within the TTL is a compute problem, not a cryptographic one. A limit turns the attack from “finish the space” into “get lucky in a few tries,” while still having to spare legitimate mistakes: a typo, an extra pasted digit, autofill that fails then retries. IP-only throttles fall to shared egress; account-only throttles become denial of service against one person. A sturdier unit is this challenge: count failures against the code that was sent, reset when that code dies, count again on the next code. If the box still looks submittable after the budget is gone, people think the code was wrong rather than that the window closed, resend in a loop, and lock themselves on the channel throttle.
Studying it
On a controlled check API, compare unlimited, IP-only throttle, and per-challenge limits: requests needed for a lucky hit, and whether a normal typo still allows completion.
Independent variables: allowed failures, counting key (IP, account, challenge id), silent failure versus voiding the code at the cap, remaining-attempt copy. Dependent variables: random-guess hit rate (should sit at chance and drop to zero after the cap), completion after one honest typo, extra resends caused by the limit.
Do not publish a universal “N tries is safe”; space, TTL, and check rate jointly size the window, and lab numbers are not a product quota. Human studies should focus on copy at the cap: whether people understand they must request a new code rather than keep editing the last digit.
Where it stops holding
Authenticator TOTP rolls every 30 seconds; limits must follow windows, not a lifetime of three tries, or people with clock skew are locked forever. Codes spoken over voice are misheard more often; a tight cap pushes people onto a weaker channel. Offline checks have no online verifier, so attempt limits do not apply. Long account-wide lockouts turn enumeration defense into denial of service against the owner; voiding this code and briefly refusing checks aims at the threat more closely. Send-side throttles on mail or SMS are a second limiter; stacking them must not leave someone unable both to try and to request.
Applying it
- Count failed checks per “code from this send”; at the cap, void that code and require a resend. Do not rely on IP throttle atop unlimited submits.
- Near the cap, say how many tries remain; at zero, change copy to “request a new code” and disable submit until a new code is issued.
- Normalize paste artifacts (spaces, newlines) before counting a failure, so an autofill format glitch does not burn the budget.
- Verify with a script submitting more than the cap of random codes against one challenge: no sign-in, and later random codes also fail. Then have a person mistype once and paste the correct code; they should still pass. Failed checks in logs should hang off the challenge id, not IP alone.
Related
- Within the group: H6.03.1 OTP fields must accept paste and autofill · H6.03.2 OTP expiry and resend interval must be visible · H6.03.3 SMS failure needs a fallback channel · H6.03.4 A magic link must expire after one use so forwarding cannot reuse it · H6.03.6 Magic links and OTP codes are not equivalent authenticators · H6.03.7 Passwordless login still needs a device-side confirmation against intercepted links
- Adjacent: H6.04 Password rules · H6.11 Password recovery and reset
- Search terms:
OTP brute force·online guessing·authentication rate limit
Cards in the same group
- H6.03.1OTP fields must accept paste and autofill
- H6.03.2OTP expiry and resend interval must be visible
- H6.03.3SMS failure needs a fallback channel
- H6.03.4A magic link must expire after one use so forwarding cannot reuse it
- H6.03.6Magic links and OTP codes are not equivalent authenticators
- H6.03.7Passwordless login still needs a device-side confirmation against intercepted links