From 3e165a8c6fea303250e626dc952a396e40887c71 Mon Sep 17 00:00:00 2001 From: "Rudy B." Date: Sat, 25 Apr 2026 18:51:03 +0200 Subject: [PATCH] fix(2FA): backup code double-use race condition --- src/app/api/2fa/verify/route.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/app/api/2fa/verify/route.ts b/src/app/api/2fa/verify/route.ts index 636af3caa..eea621b2b 100644 --- a/src/app/api/2fa/verify/route.ts +++ b/src/app/api/2fa/verify/route.ts @@ -81,10 +81,20 @@ export async function POST(request: Request) { }); } - await prisma.client.twoFactorBackupCode.update({ - where: { id: unusedCodes[matchIndex].id }, + const consumed = await prisma.client.twoFactorBackupCode.updateMany({ + where: { id: unusedCodes[matchIndex].id, used: false }, data: { used: true }, }); + + if (consumed.count === 0) { + const { lockedUntil } = await recordFailedAttempt(userId); + return badRequest({ + code: 'two-factor-error-invalid-backup-code', + message: 'Invalid backup code', + ...(lockedUntil && { lockedUntil }), + }); + } + await resetRateLimit(userId); } else { const { token } = body;