Skip to content

feat(security): prevent user enumeration via timing attacks#2223

Closed
maxdinech wants to merge 1 commit intosupabase:masterfrom
Delos-Intelligence:feat/prevent-user-enumeration-timing-attack
Closed

feat(security): prevent user enumeration via timing attacks#2223
maxdinech wants to merge 1 commit intosupabase:masterfrom
Delos-Intelligence:feat/prevent-user-enumeration-timing-attack

Conversation

@maxdinech
Copy link

What kind of change does this PR introduce?

Feature - Security enhancement

What is the current behavior?

Password authentication endpoints leak information about user existence through timing differences:

  • Valid users (wrong password): ~120-150ms (includes DB eager loading + bcrypt)
  • Invalid users: ~10-20ms (fast DB lookup, no bcrypt)

This timing difference allows attackers to enumerate valid email addresses/phone numbers by measuring response times, even without rate limiting bypass.

We discovered this vulnerability during a penetration test of our self-hosted Supabase instance. Testing showed a consistent 100ms+ difference that reliably identified valid accounts.

What is the new behavior?

Adds a new configuration option GOTRUE_SECURITY_TIMING_OBFUSCATION_DELAY that adds timing obfuscation to invalid login attempts.

Changes:

  • Added GOTRUE_SECURITY_TIMING_OBFUSCATION_DELAY configuration option
  • Invalid user lookups now perform dummy bcrypt comparison (same cost as real passwords)
  • Configurable additional delay compensates for database eager loading overhead
  • Applied to both "user not found" and "user has no password" cases

Implementation details:

  • Uses pre-computed bcrypt hash (cost 10) for consistent timing
  • Bcrypt operation auto-scales with CPU speed (~50-200ms)
  • Additional delay compensates for .Eager() loading of Factors/Identities (~30-50ms)
  • Recommended value: 40ms (empirically tested to overlap timing ranges)
  • Disabled by default (opt-in security enhancement)
  • No database schema changes required

Testing performed

Timing analysis on staging environment (20 samples each):

  • Before fix: 113ms average difference (VULNERABLE)
  • After fix (40ms delay): 7ms average difference with overlapping ranges (PROTECTED)

Valid user and invalid user response times now overlap significantly, preventing reliable enumeration.

Adds timing obfuscation to password authentication to prevent user enumeration.
Configurable via GOTRUE_SECURITY_TIMING_OBFUSCATION_DELAY (default: 0, disabled).
Recommended value: 40ms for typical workloads.
@maxdinech maxdinech requested a review from a team as a code owner October 21, 2025 10:37
@maxdinech
Copy link
Author

maxdinech commented Oct 21, 2025

Note : on more powerful instances, a value of just 10ms for GOTRUE_SECURITY_TIMING_OBFUSCATION_DELAY can be sufficient. The main introduction of that PR is to force some bcrypt call even on the case where the user is not found.

@hf
Copy link
Contributor

hf commented Oct 29, 2025

Thank you for this PR. We do not plan on adding timing obfuscation on this endpoint at this time. It's a guessing game, and making requests slower has other resource implications.

We do believe that en-masse user enumeration can be prevented by adequately configuring rate limiting and captcha.

@hf hf closed this Oct 29, 2025
@hf
Copy link
Contributor

hf commented Oct 29, 2025

Also @maxdinech please review Supabase's security.txt file before submitting more fixes that might indicate potential security issues. Please follow a responsible security vulnerability (even if suspected) process.

https://supabase.com/.well-known/security.txt

@maxdinech maxdinech deleted the feat/prevent-user-enumeration-timing-attack branch December 3, 2025 11:50
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.

2 participants