Skip to content

Fix OTP Concurrency Race Conditions#5

Closed
Maatify wants to merge 3 commits intomainfrom
fix-concurrency-vulnerabilities-6459033912038507901
Closed

Fix OTP Concurrency Race Conditions#5
Maatify wants to merge 3 commits intomainfrom
fix-concurrency-vulnerabilities-6459033912038507901

Conversation

@Maatify
Copy link
Owner

@Maatify Maatify commented Mar 14, 2026

Summary

Addresses critical concurrency vulnerabilities identified in the recent security audit. The maatify/verification module is now safe against brute-force amplification and generation-limit bypassing under high concurrency.

Changes

  • Database Schema: Introduced verification_generation_locks table in database/verification_generation_locks.sql.
  • Validation Flow: Refactored VerificationCodeValidator to delegate state enforcement (OTP hash, expiration, attempt counts) entirely to an atomic database query (markUsed). This prevents TOCTOU race conditions where multiple requests could bypass the attempt limit.
  • Generation Flow: Added acquireGenerationLock to PdoVerificationCodeRepository which upserts and locks a row in the new verification_generation_locks table. This prevents empty-set race conditions where multiple concurrent generation requests could insert OTPs simultaneously.
  • Dependency Update: Cleaned up constructor for VerificationCodeValidator as ClockInterface is no longer needed since expiration is handled in the query.

PR created automatically by Jules for task 6459033912038507901 started by @Maatify

…tion locks

This commit completely resolves the Time-Of-Check to Time-Of-Use (TOCTOU)
race conditions in the OTP validation and generation flows.

Validation:
- Removed in-memory comparison logic for `attempts` and `hash`.
- Replaced with a single, atomic `markUsed()` SQL update.
- Updated `incrementAttempts()` to safely target only the latest active challenge.

Generation:
- Solved the empty-lock race condition where `FOR UPDATE` failed to lock when 0 codes existed.
- Added `verification_generation_locks` table to act as a persistent mutex anchor.
- Updated `lockActiveForUpdate()` usage to properly lock the identity scope before querying.

Co-authored-by: Maatify <130119162+Maatify@users.noreply.github.com>
@google-labs-jules
Copy link

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

google-labs-jules bot and others added 2 commits March 14, 2026 02:50
- Fixed `markUsed()` to strictly update exactly one valid challenge row matching the code hash, to prevent consuming multiple codes if duplicates were somehow generated. Returned boolean check strictly uses `rowCount() === 1`.
- Fixed `incrementAttempts()` to ensure it only increments attempts on active challenges that are still not expired by time (`expires_at >= :now`).

Co-authored-by: Maatify <130119162+Maatify@users.noreply.github.com>
…e path

- Added `AND attempts < max_attempts` to the target selection logic of `incrementAttempts()`.
- This ensures that failed validation guesses never increment a row that has already been exhausted but hasn't had its status transitioned yet due to timing.

Co-authored-by: Maatify <130119162+Maatify@users.noreply.github.com>
@Maatify Maatify closed this Mar 16, 2026
@Maatify Maatify deleted the fix-concurrency-vulnerabilities-6459033912038507901 branch March 16, 2026 01:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant