Skip to content

fix: add stricter rules for the admin email field#441

Merged
khendrikse merged 3 commits into
masterfrom
SEC-860/stricter-from-email-rules
May 19, 2026
Merged

fix: add stricter rules for the admin email field#441
khendrikse merged 3 commits into
masterfrom
SEC-860/stricter-from-email-rules

Conversation

@khendrikse
Copy link
Copy Markdown
Contributor

@khendrikse khendrikse commented May 13, 2026

- Summary

Adds validation to SMTPConfiguration that rejects admin_email values that the gotrue entity does not allow. Closing a vulnerability where an attacker could send SPF/DKIM/DMARC-authenticated phishing emails from team@example.com via the default mail infrastructure. Validation runs at update time in UpdateInstance and covers exact domain matches, subdomains, and invalid email formats.

- Test plan

- Description for the changelog

- A picture of a cute animal (not mandatory but encouraged)

@khendrikse khendrikse requested a review from a team as a code owner May 13, 2026 09:37
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 13, 2026

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6f5d03c3-db99-432d-a634-fb6aabb01c64

📥 Commits

Reviewing files that changed from the base of the PR and between 7b85b84 and 2ef740a.

📒 Files selected for processing (3)
  • README.md
  • conf/configuration.go
  • conf/configuration_test.go
✅ Files skipped from review due to trivial changes (1)
  • README.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • conf/configuration_test.go

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • SMTP validation added; new SMTP_RESERVED_DOMAINS option to restrict sender domains.
  • Bug Fixes

    • API endpoints now return clear 400 responses when SMTP configuration is invalid.
  • Documentation

    • Updated README documenting SMTP_RESERVED_DOMAINS and domain restriction behavior.
  • Tests

    • Added unit tests covering SMTP configuration validation and reserved-domain handling.

Walkthrough

Adds SMTP admin email validation: a new SMTPConfiguration.Validate() parses AdminEmail, rejects addresses whose domain equals or is a subdomain of any configured ReservedDomains, exposes ReservedDomains in SMTPConfiguration, adds a table-driven unit test, documents SMTP_RESERVED_DOMAINS in the README, and invokes Validate() from CreateInstance and UpdateInstance when BaseConfig is provided, returning 400 on validation failure.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding stricter validation rules for the admin email field to prevent phishing attacks.
Description check ✅ Passed The description is related to the changeset, explaining the security vulnerability being addressed and the validation approach implemented across the modified files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch SEC-860/stricter-from-email-rules

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

Error: can't load config: unsupported version of the configuration: "" See https://golangci-lint.run/docs/product/migration-guide for migration instructions
The command is terminated due to an error: can't load config: unsupported version of the configuration: "" See https://golangci-lint.run/docs/product/migration-guide for migration instructions


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
conf/configuration_test.go (1)

33-39: ⚡ Quick win

Add a regression case for quoted local-parts containing @.

Please add a case like "\"a@b\"@netlify.com" expecting an error, so this bypass path stays covered long-term.

🧪 Suggested test case addition
 	{
 		{"", false},                     // empty is fine
 		{"noreply@example.com", false},  // valid non-Netlify domain
 		{"team@netlify.com", true},      // reserved domain
 		{"user@netlify.app", true},      // reserved domain
 		{"user@sub.netlify.com", true},  // subdomain of reserved
+		{"\"a@b\"@netlify.com", true},   // quoted local-part with '@' must still be blocked
 		{"not-an-email", true},          // invalid format
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@conf/configuration_test.go` around lines 33 - 39, Add a regression test entry
for quoted local-parts containing @ by inserting the case
{"\"a@b\"@netlify.com", true} into the existing test cases array in
configuration_test.go (the same table with entries like {"noreply@example.com",
false} and {"team@netlify.com", true}) so the validation logic that handles
quoted local-parts is exercised and expected to error; ensure the string is
properly escaped in the Go source.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@api/instance.go`:
- Around line 111-115: CreateInstance currently skips SMTP validation allowing
bypass of reserved-domain rules; add the same SMTP config validation used in the
update path by invoking params.BaseConfig.SMTP.Validate() inside CreateInstance
(the same check you see in the UpdateInstance branch) and return
badRequestError("Invalid SMTP configuration: %v", err) on failure so
BaseConfig.SMTP.AdminEmail is enforced at creation time as well.

In `@conf/configuration.go`:
- Around line 297-305: The current validation uses strings.Split(addr.Address,
"@") which fails for quoted local-parts containing '@' (e.g.,
"\"a@b\"@netlify.com") and thus skips reserved-domain checks; change the logic
in the block that reads addr.Address to find the last '@' using
strings.LastIndex, if idx >= 0 extract domain :=
strings.ToLower(addr.Address[idx+1:]), then iterate over reservedDomains and use
domain == reserved or strings.HasSuffix(domain, "."+reserved) to return the same
error; also handle the case idx < 0 by skipping validation (or treating as
invalid per existing behavior) so behavior is correct for RFC5322 addresses.

---

Nitpick comments:
In `@conf/configuration_test.go`:
- Around line 33-39: Add a regression test entry for quoted local-parts
containing @ by inserting the case {"\"a@b\"@netlify.com", true} into the
existing test cases array in configuration_test.go (the same table with entries
like {"noreply@example.com", false} and {"team@netlify.com", true}) so the
validation logic that handles quoted local-parts is exercised and expected to
error; ensure the string is properly escaped in the Go source.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bfcb455c-1810-4382-8b44-d74e3e002906

📥 Commits

Reviewing files that changed from the base of the PR and between ab1bf15 and 7614198.

📒 Files selected for processing (3)
  • api/instance.go
  • conf/configuration.go
  • conf/configuration_test.go

Comment thread api/instance.go
Comment thread conf/configuration.go Outdated
@khendrikse khendrikse requested a review from VaibhavAcharya May 18, 2026 13:53
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@conf/configuration.go`:
- Around line 298-301: The comparison against s.ReservedDomains is using a
normalized domain variable but comparing it to raw reserved entries, allowing
bypasses; update the check in the loop that iterates s.ReservedDomains (the
block that computes domain from addr.Address) to normalize each reserved entry
before comparing - e.g., apply strings.TrimSpace, strings.ToLower and remove any
trailing dot characters from the reserved string, then compare
normalizedReserved == domain or strings.HasSuffix(domain,
"."+normalizedReserved) so entries like " Netlify.COM." match correctly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c22db56b-019b-4f81-aa11-7b8f3195b144

📥 Commits

Reviewing files that changed from the base of the PR and between 10a228b and 9b1decd.

📒 Files selected for processing (3)
  • README.md
  • conf/configuration.go
  • conf/configuration_test.go

Comment thread conf/configuration.go
@khendrikse khendrikse force-pushed the SEC-860/stricter-from-email-rules branch from 9b1decd to 7b85b84 Compare May 19, 2026 06:44
@khendrikse khendrikse force-pushed the SEC-860/stricter-from-email-rules branch from 7b85b84 to 2ef740a Compare May 19, 2026 09:32
@khendrikse khendrikse merged commit 738d5b4 into master May 19, 2026
7 checks passed
@khendrikse khendrikse deleted the SEC-860/stricter-from-email-rules branch May 19, 2026 12:39
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