Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

Email OTP login has no attempt limit: useVerificationToken doesn't invalidate the code on a wrong guess (brute-forceable account takeover)

Abierto
#2,221 2 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

@addyCooks ya está trabajando en esto.

Desde el 5/9/2026.

  • #2224 de @addyCooks — abierto
  • #2269 de @mini0n-ai — abierto
  • #2286 de @massmarketconsumer-arch — abierto

Evaluación

Dificultad
3/5
Tiempo estimado
1-2 días
Aptitud para principiantes
78/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
nextjs, typescript

Línea de trabajo

Comienza en packages/database/auth/drizzle-adapter.ts, en useVerificationToken, y compara después su gestión de discrepancias con apps/web/app/api/mobile/[...route]/route.ts:543-548. Revisa el punto de entrada del callback de correo electrónico y las comprobaciones de auth existentes antes de validar el comportamiento. Se considera terminado cuando un código incorrecto invalida la fila de verificación y no se puede volver a intentar, mientras que la verificación correcta sigue funcionando.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

bug
Summary

useVerificationToken in packages/database/auth/drizzle-adapter.ts (lines 512-538) only
deletes the verification row on a successful match. A wrong 6-digit code guess finds no row
(lookup is by exact token value), logs a warning, and returns null the real code is left
untouched. It can be guessed without limit for its entire TTL (10 minutes as of #2068).

This is a logic bug, not just a missing rate limit: the mobile login path already does this
correctly. apps/web/app/api/mobile/[...route]/route.ts:543-548 deletes the row on a token
mismatch before returning "invalid", burning the code on the first wrong attempt. The web
(NextAuth) path has no equivalent.

Repro
  1. POST /api/auth/signin/email for a target address.
  2. Fire guesses at GET /api/auth/callback/email?email=<target>&token=<6-digit>.
  3. Codes come from crypto.randomInt(100000, 1000000) (900,000 possible values,
    auth-options.ts:138). At ~100 req/s, ~6.7% success chance within the 10-minute window;
    sustained guessing lands a hit in a few hours.
Why this isn't closed by existing rate-limit ids

RATE_LIMIT_IDS.AUTH_OTP_VERIFY / AUTH_OTP_SEND (apps/web/lib/rate-limit.ts:83-85) are
declared but have zero call sites (see #2039, PR #1924 open and stale since June, PR #2040
closed without wiring these two). Even once wired, isRateLimited is backed by Vercel Firewall
and fails open without a matching dashboard rule, so it provides no protection on self-hosted
deployments
regardless. The durable, hosting-agnostic fix has to live in
useVerificationToken itself.

Suggested fix

Delete (or otherwise invalidate) the verification row on a failed match too, not only on
success mirroring the mobile implementation. Wiring AUTH_OTP_VERIFY/AUTH_OTP_SEND as
defense-in-depth on Vercel deployments is worth doing separately, but shouldn't be treated as
the fix on its own since it doesn't cover self-hosted instances.

Related
  • #2039 (open), broader unwired-rate-limit-ids issue, includes these two ids but not this root cause
  • #1924 (open, stale), Firewall-based rate limiting, never merged
  • #2068 (merged), fixed the 24h→10min window, explicitly left the attempt-counter fix as follow-up
  • #2040 (closed), deliberately punted on wiring these two ids
Lenguaje dominante
Rust
Estrellas
23k
Forks
2k
Merge medio
13 h 2 min
PR fusionados (30 d)
70

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de CapSoftware/Cap

Todos los issues de CapSoftware/Cap

Issues similares

Más issues de Rust

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.