highhigh confidenceCWE-640authenticationOpen
Password reset links never expire and survive a password change
lib/auth/reset.ts:23
Impact
A password reset link found in an old email, a shared inbox or a proxy log still works months later, even after the user changed their password.
Attack path
2 steps- Step 1: lib/auth/reset.ts:23EntryTokens are stored without an expiry and never invalidated on use.
22 await db.resetTokens.insert({ userId, token: hash(token) }); - Step 2: app/reset/[token]/page.tsx:12SinkLookup checks existence only.
11 const row = await db.resetTokens.find({ token: hash(params.token) });
Fix
Store an expiry (30 minutes is typical), delete the token on use, and delete all of a user's tokens when their password changes.