Skip to content

fix(api): prevent OTP backup code replay#122

Merged
markwylde merged 1 commit intomainfrom
codex/fix-otp-backup-code-reuse-vulnerability
Mar 10, 2026
Merged

fix(api): prevent OTP backup code replay#122
markwylde merged 1 commit intomainfrom
codex/fix-otp-backup-code-reuse-vulnerability

Conversation

@markwylde
Copy link
Copy Markdown
Member

Motivation

  • The OTP backup-code verification path did not exclude entries where usedAt was already set, allowing previously consumed backup codes to be replayed indefinitely and bypass one-time semantics.

Description

  • Added isNull import from drizzle-orm and changed the backup-code lookup to only select rows where usedAt IS NULL in packages/api/src/models/otp.ts.
  • Hardened the consume/update statement to only set usedAt when the row is still unused by adding isNull(otpBackupCodes.usedAt) to the update WHERE clause in packages/api/src/models/otp.ts.
  • These changes enforce one-time use while preserving the existing OTP verification flow and behavior for TOTP codes.

Testing

  • Ran npm run tidy at the repo root which completed (existing linter warnings/info remain unrelated to this change).
  • Ran npm run build at the repo root which completed (brochureware prebuild logged a missing puppeteer dependency but overall build finished).
  • Ran npm -w packages/api test which failed in this environment due to Node executing .ts tests without a configured TypeScript test loader (ERR_UNKNOWN_FILE_EXTENSION), which is unrelated to the OTP logic changes.

Codex Task

@markwylde markwylde merged commit 994eda0 into main Mar 10, 2026
19 of 20 checks passed
@markwylde markwylde deleted the codex/fix-otp-backup-code-reuse-vulnerability branch March 10, 2026 18:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant