Skip to content

fix: add client-side disposable email check in CLI login#188

Merged
SecurityQQ merged 1 commit intomainfrom
fix/block-disposable-emails
Mar 31, 2026
Merged

fix: add client-side disposable email check in CLI login#188
SecurityQQ merged 1 commit intomainfrom
fix/block-disposable-emails

Conversation

@SecurityQQ
Copy link
Copy Markdown
Contributor

Summary

Add a lightweight client-side check for common disposable email domains in the CLI login flow for instant UX feedback.

Changes

  • Add inline blocklist of ~30 most common disposable email domains (guerrillamail, yopmail, tempmail, mailinator, etc.)
  • Check runs before the network request to /api/auth/cli/send-otp
  • If matched, shows error immediately without waiting for server round-trip

Note

This is purely a UX optimization. The real enforcement happens server-side in the app repo where mailchecker (55k+ domains) blocks disposable emails at the /api/auth/cli/send-otp endpoint. This client-side check just makes the rejection faster for the most common offenders.

Related PRs

  • app: vargHQ/app — server-side disposable email blocking (CLI + web)
  • gateway: vargHQ/gateway — admin set-balance, ban endpoint, cleanup script

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 30, 2026

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: ddbd6f86-141b-477d-8946-1bfd7074a541

📥 Commits

Reviewing files that changed from the base of the PR and between 0bf192d and 8a67157.

📒 Files selected for processing (1)
  • src/cli/commands/login.tsx
✅ Files skipped from review due to trivial changes (1)
  • src/cli/commands/login.tsx

📝 Walkthrough

Walkthrough

added a client-side disposable-email guard in the login flow: after email format validation the domain is normalized and checked against an in-file set of disposable domains (including subdomain matches); if matched, the function logs an error and returns null before otp is sent.

Changes

Cohort / File(s) Summary
disposable email validation
src/cli/commands/login.tsx
added domain extraction, lowercase normalization, and a Set-based disposable domain check with endsWith subdomain matching; returns null and aborts before otp dispatch when matched.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🚫✉️ tiny throwaway domains, no entry here,
the login gate says stop, move along, dear,
one quick check, one gentle meow,
auth stays clean — nice and mellow now. 😺

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed the title clearly and directly summarizes the main change: adding a client-side disposable email check in the CLI login flow.
Description check ✅ Passed the description is directly related to the changeset, providing clear context about the disposable email blocklist, where it runs, and its purpose as a UX optimization.

✏️ 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 fix/block-disposable-emails

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown
Contributor

@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 the current code and only fix it if needed.

Inline comments:
In `@src/cli/commands/login.tsx`:
- Around line 234-269: The client-side disposable domain check recreates
DISPOSABLE_DOMAINS on every login and only matches exact domains, missing
subdomains and violating camelCase rules; move the domain list into a
module-level camelCase constant (e.g., disposableDomains as a Set) so it’s
created once, and change the runtime check in the login flow (where domain is
computed from email) to treat subdomains as disposable by checking either
set.has(domain) OR testing domain.endsWith("." + candidate) for any candidate in
the Set (or normalize by stripping subdomains and checking the apex), ensuring
you reference the existing domain variable and the new disposableDomains symbol.
🪄 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: 04ed6fc6-4e9f-4afe-ade9-3a7fc24db107

📥 Commits

Reviewing files that changed from the base of the PR and between 40813d4 and 0bf192d.

📒 Files selected for processing (1)
  • src/cli/commands/login.tsx

Comment on lines +234 to +269
const domain = email.split("@")[1]?.toLowerCase();
const DISPOSABLE_DOMAINS = new Set([
"guerrillamail.com",
"guerrillamailblock.com",
"guerrillamail.net",
"guerrillamail.org",
"guerrillamail.de",
"grr.la",
"sharklasers.com",
"guerrilla.ml",
"yopmail.com",
"yopmail.fr",
"yopmail.net",
"tempmail.com",
"temp-mail.org",
"temp-mail.io",
"mailinator.com",
"mailinator2.com",
"throwaway.email",
"throwaway.email",
"trashmail.com",
"trashmail.net",
"trashmail.me",
"10minutemail.com",
"10minutemail.net",
"dispostable.com",
"maildrop.cc",
"fakeinbox.com",
"mailnesia.com",
"tempail.com",
"tempr.email",
"discard.email",
"discardmail.com",
"mohmal.com",
"burpcollaborator.net",
]);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

client check misses subdomains and does extra work each call

on Line 271, Set.has(domain) only catches exact matches, so disposable subdomains can slip through client-side. also, Line 235 recreates the set every login attempt, and DISPOSABLE_DOMAINS breaks the repo’s camelCase variable rule.

suggested cleanup + stronger match
+const disposableDomains = new Set([
+  "guerrillamail.com",
+  "guerrillamailblock.com",
+  "guerrillamail.net",
+  "guerrillamail.org",
+  "guerrillamail.de",
+  "grr.la",
+  "sharklasers.com",
+  "guerrilla.ml",
+  "yopmail.com",
+  "yopmail.fr",
+  "yopmail.net",
+  "tempmail.com",
+  "temp-mail.org",
+  "temp-mail.io",
+  "mailinator.com",
+  "mailinator2.com",
+  "throwaway.email",
+  "trashmail.com",
+  "trashmail.net",
+  "trashmail.me",
+  "10minutemail.com",
+  "10minutemail.net",
+  "dispostable.com",
+  "maildrop.cc",
+  "fakeinbox.com",
+  "mailnesia.com",
+  "tempail.com",
+  "tempr.email",
+  "discard.email",
+  "discardmail.com",
+  "mohmal.com",
+  "burpcollaborator.net",
+]);
+
+const isDisposableDomain = (domain: string): boolean => {
+  if (disposableDomains.has(domain)) {
+    return true;
+  }
+  for (const blockedDomain of disposableDomains) {
+    if (domain.endsWith(`.${blockedDomain}`)) {
+      return true;
+    }
+  }
+  return false;
+};
+
 async function loginWithEmail(): Promise<LoginResult | null> {
@@
-  const domain = email.split("@")[1]?.toLowerCase();
-  const DISPOSABLE_DOMAINS = new Set([
-    ...
-  ]);
+  const domain = email.split("@")[1]?.toLowerCase();
@@
-  if (domain && DISPOSABLE_DOMAINS.has(domain)) {
+  if (domain && isDisposableDomain(domain)) {
     log.error(
       "Disposable email addresses are not allowed. Please use a permanent email address.",
     );
     return null;
   }

As per coding guidelines, "Use camelCase for variable and function names".

Also applies to: 271-271

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/cli/commands/login.tsx` around lines 234 - 269, The client-side
disposable domain check recreates DISPOSABLE_DOMAINS on every login and only
matches exact domains, missing subdomains and violating camelCase rules; move
the domain list into a module-level camelCase constant (e.g., disposableDomains
as a Set) so it’s created once, and change the runtime check in the login flow
(where domain is computed from email) to treat subdomains as disposable by
checking either set.has(domain) OR testing domain.endsWith("." + candidate) for
any candidate in the Set (or normalize by stripping subdomains and checking the
apex), ensuring you reference the existing domain variable and the new
disposableDomains symbol.

- Add module-level DISPOSABLE_DOMAINS constant (created once, not per call)
- Add isDisposableDomain() helper with subdomain matching
  (e.g. sub.guerrillamail.com is also caught)
- Lightweight inline list (~30 domains) for instant UX feedback;
  server-side mailchecker (55k+ domains) is the real enforcement
@SecurityQQ SecurityQQ force-pushed the fix/block-disposable-emails branch from 0bf192d to 8a67157 Compare March 31, 2026 00:10
@SecurityQQ SecurityQQ merged commit 6d238e4 into main Mar 31, 2026
2 checks passed
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