Skip to content

Delos Security Patches (v2.184.0-rc.4)#3

Draft
maxdinech wants to merge 9 commits intomainfrom
delos-production
Draft

Delos Security Patches (v2.184.0-rc.4)#3
maxdinech wants to merge 9 commits intomainfrom
delos-production

Conversation

@maxdinech
Copy link

Delos Custom Security Patches

This PR tracks our custom security patches on top of upstream Supabase Auth rc2.184.0-rc.4.

⚠️ This PR should never be merged - it exists to:

  • Provide a visual diff of our customizations
  • Document what's different from upstream
  • Help detect conflicts when syncing with new upstream releases

Patches Included

1. 🛡️ Timing Attack Prevention

2. 🔒 Cache-Control Headers

3. 🔑 Require Current Password

4. 🚫 OTP Brute Force Protection

  • What: Limits OTP verification attempts to 3, then invalidates token
  • Why: 6-digit codes can be brute-forced without rate limiting
  • Implementation: Custom - not submitted to upstream yet
  • Changes:
    • Migration adds attempt_count and invalidated_at columns to auth.one_time_tokens
    • Tracks failed attempts across all OTP verification types
    • Auto-invalidates after 3 failed attempts

Changed Files

```
13 files changed, 173 insertions(+), 12 deletions(-)
```

Maintenance

When syncing with new upstream releases:

  1. Update main branch: git fetch upstream && git merge upstream/main
  2. Rebase this branch: git rebase main delos-production
  3. Review this PR for conflicts
  4. Force push: git push origin delos-production --force-with-lease

Testing Checklist

  • Timing attack prevention works with GOTRUE_SECURITY_TIMING_OBFUSCATION_DELAY=40
  • Token endpoints return proper Cache-Control headers
  • Password change requires current password when enabled
  • OTP tokens invalidate after 3 failed attempts
  • New OTP generation resets attempt counter

fadymak and others added 9 commits November 25, 2025 12:37
We have an existing `UNIQUE` index on the `phone` column
(`users_phone_key`) that can be reused for:

1. Exact match queries
2. Prefixed search queries (`phone LIKE '123%'`) or range-based queries
(`phone > '123' AND phone < '123'`)
3. Order by clauses `ORDER BY phone`

`text_pattern_ops` indexes do not support ordering.
Uses structured logging in the indexworker to make it easier to query
events.
When template reloading is disabled start a goroutine to warm the
template cache early in startup.

---------

Co-authored-by: Chris Stockton <chris.stockton@supabase.io>
Adds support for X (formerly Twitter) v2 as an external OAuth provider.

- Introduces an `oauth_client_states` table to persist the `code_verifier`s as
X mandates the use of PKCE
- Uses SHA256 challenge for PKCE
- Updates the `GetOAuthToken` signature to accept a `code_verifier` as
the second parameter
- Uses the existing cleanup middleware to delete states
- Adds the provider as `x` rather than `x_v2` as `twitter` is already
used in old OAuth 1.0a provider to better align with the rebrand
- The state is a UUIDv4

NOTE: today the `flow_states` table is overloaded, containing states,
auth codes, provider tokens...the goal is to decouple that table
eventually and the `oauth_states` table is the first step towards that.
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.
…caching

Token endpoints (password grant, refresh token, PKCE, MFA, etc.) were
missing Cache-Control headers, allowing browsers to cache JWT tokens
in memory. This violates RFC 6749 Section 5.1 which requires token
responses to include 'Cache-Control: no-store'.

Security Impact:
- Browsers like Firefox cache token responses in about:cache
- Attackers with physical access can extract cached JWT tokens
- Leads to potential session hijacking

Changes:
- Add sendTokenJSON helper function with no-store cache headers
- Update all token-returning endpoints to use sendTokenJSON
- Covers password, refresh, PKCE, MFA, OIDC, Web3, anonymous, signup, and verify flows

Fixes discovered during professional security audit (OWASP OTG-AUTHN-006).
…pdates

Adds a new configuration option GOTRUE_SECURITY_UPDATE_PASSWORD_REQUIRE_CURRENT_PASSWORD
that addresses session hijacking vulnerabilities by requiring users to provide their
current password when changing to a new password.

When enabled, the PUT /user endpoint requires a current_password field in the request
body alongside the new password. The current password is verified before allowing the
password change, preventing attackers with stolen session tokens from changing passwords
without knowledge of the current password.

This security feature works alongside the existing UpdatePasswordRequireReauthentication
option and is disabled by default for backwards compatibility.

Related to discussion #32972
- Add attempt_count and invalidated_at columns to auth.one_time_tokens
- Track failed OTP verification attempts (max 3)
- Invalidate token after 3 failed attempts
- Add Email field to VerifyParams for user lookup
- Implement protection in signupVerify and recoverVerify
- Helper functions: checkOTPTokenInvalidated, recordOTPAttempt, clearOTPAttempts
- Remove GOTRUE_SECURITY_TIMING_OBFUSCATION_DELAY config option
- Keep bcrypt-based timing obfuscation (provides ~100ms constant time)
- Simplify implementation while maintaining protection against basic timing attacks
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.

3 participants