A stolen refresh token survived a password-forgot flow and could be used to mint fresh JWTs even after the user reset their password.
passwordChange and passwordReset deleted the user's refresh tokens, but
passwordForgot only rotated token_version and revoked OAuth tokens — it did not
call UserRefreshToken.deleteAllUserToken(user.id). An attacker holding a captured
refresh cookie could still exchange it for a new access token after the victim
triggered the recovery flow.
Persistent unauthorized access after password recovery. Once a refresh token leaks, the documented "Forgot password" recovery flow did not in fact revoke the attacker's session.
This issue was reported by @bugbunny-research.
{
"nvd_published_at": null,
"cwe_ids": [
"CWE-613"
],
"github_reviewed": true,
"severity": "MODERATE",
"github_reviewed_at": "2026-06-17T14:07:33Z"
}