') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); fix: tighten email validation rules by cstockton · Pull Request #2304 · supabase/auth · GitHub
Skip to content

fix: tighten email validation rules - #2304

Merged
cstockton merged 2 commits into
masterfrom
cs/update-email-validation
Dec 23, 2025
Merged

fix: tighten email validation rules#2304
cstockton merged 2 commits into
masterfrom
cs/update-email-validation

Conversation

@cstockton

@cstocktoncstockton commented Dec 22, 2025

Copy link
Copy Markdown
Contributor

The goal here is to limit the conditions which resolver implementations can affect the determinism of our DNS checks, without allowing transient DNS failures to block signups:

  • Reject single label email domains (a@a, a@gmail)
  • Use absolute FQDN for DNS lookups to avoid implicit search behavior
  • Preserves the RFC 5321 fallback, but narrows when it is called
  • Add an allow list for major email providers to lower latency
  • Reject mutated display name address that the mail parser might accept
  • Add test coverage for some corner cases

@cstockton
cstockton requested a review from a team as a code ownerDecember 22, 2025 18:38
@coveralls

coveralls commented Dec 22, 2025

Copy link
Copy Markdown

Pull Request Test Coverage Report for Build 20462025333

Warning: This coverage report may be inaccurate.

This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.

Details

  • 16 of 16(100.0%) changed or added relevant lines in 1 file are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.1%) to 68.784%

TotalsCoverage Status
Change from base Build 20445257346:0.1%
Covered Lines:14728
Relevant Lines:21412

💛 - Coveralls

implementations can affect the determinism of our DNS
checks, without allowing transient DNS failures to block signups:
* Reject single label email domains (`a@a`, `a@gmail`)
* Use absolute FQDN for DNS lookups to avoid implicit search behavior
* Preserves the RFC 5321 fallback, but narrows when it is called
* Add an allow list for major email providers to lower latency
* Reject mutated display name address that the mail parser might accept
* Add test coverage for some corner cases
@cstockton
cstocktonforce-pushed the cs/update-email-validation branch from 13bec55 to d32397fCompareDecember 23, 2025 13:23
hf
hf approved these changes Dec 23, 2025
@cstockton
cstockton merged commit 33bb372 into masterDec 23, 2025
6 checks passed
@cstockton
cstockton deleted the cs/update-email-validation branch December 23, 2025 14:26
cstockton added a commit that referenced this pull request Dec 23, 2025
Note: this PR depends on #2304
## Update to Go v1.25.5
As part of this upgrade several changes were needed to resolve go vet
failures around non-constant format strings:
- Updating all apierrors constructors to use const fmt strings with args
- Removing fmt.Sprintf usages that violate go vet fmt checks
- Refactoring internal error/message helpers to accept fmt + params
In addition stricter checks in the standard library for x509 certificate
creation required a change to a SAML test in internal/conf. Now I start
with a valid certificate and then set the serial number to an invalid
value. To do this I opted for a small refactor to PopulateFields to
return the cert object instead of copying the code within the test.
## Why update?
Aside from security related reasons and general best practices here are
some highlights im looking forward to!
* The [flight recorder](https://go.dev/blog/flight-recorder) could be
great for debugging performance bottlenecks. I personally am super
excited for this feature, I hope the new streamable tracing API will
enable a new class of interesting visual tools in the future.
* The [synctest](https://pkg.go.dev/testing/synctest) package means no
more DI for `now func() time.Time` :D
* Addition of [t.Context()](https://pkg.go.dev/testing#T.Context) and
[t.Cleanup(func())](https://pkg.go.dev/testing#T.Cleanup) will make
lower friction as we sever ties with our testing framework. There are
other neat API's like `T.Attr` and `T.Output`.
* The new [json/v2](https://pkg.go.dev/encoding/json/v2@go1.25.5)
package offers more efficient memory usage and faster API's. When I've
ran profiling in the past JSON is a significant portion of our CPU time
so we should see some nice gains for this.
* The new
[jsontext](https://pkg.go.dev/encoding/json/jsontext@go1.25.5#example-package-StringReplace)
may come in handy for implementing JWT templates depending on how we
want to design it.
* And much more!
---------
Co-authored-by: Chris Stockton <chris.stockton@supabase.io>
hf added a commit that referenced this pull request Jan 12, 2026
@hfhf mentioned this pull request Jan 12, 2026
cemalkilic pushed a commit that referenced this pull request Jan 12, 2026
Resets the main branch (`master`) to have the same changeset as 2.184.0
but under 2.185.0.
Original release please notes:
### Features
* Add Sb-Forwarded-For header and IP-based rate limiting
([#2295](#2295))
([e8f679b](e8f679b))
* allow amr claim to be array of strings or objects
([#2274](#2274))
([607da43](607da43))
* Treat rate limit header value as comma-separated list
([#2282](#2282))
([5f2e279](5f2e279))
### Bug Fixes
* check each type independently
([#2290](#2290))
([d9de0af](d9de0af))
* fix the wrong error return value
([#1950](#1950))
([e2dfb5d](e2dfb5d))
* **indexworker:** remove pg_trgm extension
([#2301](#2301))
([c553b10](c553b10))
* **oauth-server:** allow custom URI schemes in client redirect URIs
([#2298](#2298))
([ea72f57](ea72f57))
* tighten email validation rules
([#2304](#2304))
([33bb372](33bb372))
---------
Co-authored-by: depthfirst-app[bot] <184448029+depthfirst-app[bot]@users.noreply.github.com>
cemalkilic pushed a commit that referenced this pull request Jan 12, 2026
🤖 I have created a release *beep* *boop*
---
##
[2.185.0](v2.184.0...v2.185.0)
(2026-01-12)
### Features
* Add Sb-Forwarded-For header and IP-based rate limiting
([#2295](#2295))
([e8f679b](e8f679b))
* allow amr claim to be array of strings or objects
([#2274](#2274))
([607da43](607da43))
* reset main branch to 2.185.0
([#2325](#2325))
([b9d0500](b9d0500))
* Treat rate limit header value as comma-separated list
([#2282](#2282))
([5f2e279](5f2e279))
### Bug Fixes
* additional provider and issuer checks
([#2326](#2326))
([cb79a74](cb79a74))
* check each type independently
([#2290](#2290))
([d9de0af](d9de0af))
* fix the wrong error return value
([#1950](#1950))
([e2dfb5d](e2dfb5d))
* **indexworker:** remove pg_trgm extension
([#2301](#2301))
([c553b10](c553b10))
* **oauth-server:** allow custom URI schemes in client redirect URIs
([#2298](#2298))
([ea72f57](ea72f57))
* tighten email validation rules
([#2304](#2304))
([33bb372](33bb372))
---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Bewinxed pushed a commit that referenced this pull request Jan 19, 2026
The goal here is to limit the conditions which resolver implementations
can affect the determinism of our DNS checks, without allowing transient
DNS failures to block signups:
* Reject single label email domains (`a@a`, `a@gmail`)
* Use absolute FQDN for DNS lookups to avoid implicit search behavior
* Preserves the RFC 5321 fallback, but narrows when it is called
* Add an allow list for major email providers to lower latency
* Reject mutated display name address that the mail parser might accept
* Add test coverage for some corner cases
Co-authored-by: Chris Stockton <chris.stockton@supabase.io>
Bewinxed pushed a commit that referenced this pull request Jan 19, 2026
Note: this PR depends on #2304
## Update to Go v1.25.5
As part of this upgrade several changes were needed to resolve go vet
failures around non-constant format strings:
- Updating all apierrors constructors to use const fmt strings with args
- Removing fmt.Sprintf usages that violate go vet fmt checks
- Refactoring internal error/message helpers to accept fmt + params
In addition stricter checks in the standard library for x509 certificate
creation required a change to a SAML test in internal/conf. Now I start
with a valid certificate and then set the serial number to an invalid
value. To do this I opted for a small refactor to PopulateFields to
return the cert object instead of copying the code within the test.
## Why update?
Aside from security related reasons and general best practices here are
some highlights im looking forward to!
* The [flight recorder](https://go.dev/blog/flight-recorder) could be
great for debugging performance bottlenecks. I personally am super
excited for this feature, I hope the new streamable tracing API will
enable a new class of interesting visual tools in the future.
* The [synctest](https://pkg.go.dev/testing/synctest) package means no
more DI for `now func() time.Time` :D
* Addition of [t.Context()](https://pkg.go.dev/testing#T.Context) and
[t.Cleanup(func())](https://pkg.go.dev/testing#T.Cleanup) will make
lower friction as we sever ties with our testing framework. There are
other neat API's like `T.Attr` and `T.Output`.
* The new [json/v2](https://pkg.go.dev/encoding/json/v2@go1.25.5)
package offers more efficient memory usage and faster API's. When I've
ran profiling in the past JSON is a significant portion of our CPU time
so we should see some nice gains for this.
* The new
[jsontext](https://pkg.go.dev/encoding/json/jsontext@go1.25.5#example-package-StringReplace)
may come in handy for implementing JWT templates depending on how we
want to design it.
* And much more!
---------
Co-authored-by: Chris Stockton <chris.stockton@supabase.io>
Sign up for freeto 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

@cstockton@coveralls@hf