feat: block disposable email addresses (#6783)

* feat: block disposable email addresses

* fix typos

* remove test
This commit is contained in:
aecsocket
2026-07-20 17:57:36 +00:00
committed by GitHub
parent 9bfa7c7e4a
commit ee2ad5f05b
3 changed files with 8088 additions and 2 deletions
+2
View File
@@ -10,6 +10,8 @@ extend-exclude = [
"packages/moderation/src/data/stages/license.ts",
# contains payment card IDs like `IY1VMST1MOXS` which are flagged
"apps/labrinth/src/queue/payouts/mod.rs",
# contains domain names with deliberate typos
"apps/labrinth/assets/disposable_email_blocklist.txt"
]
[default.extend-words]
File diff suppressed because it is too large Load Diff
+17 -2
View File
@@ -61,6 +61,10 @@ use webauthn_rs::prelude::{
};
use zxcvbn::Score;
/// Sourced from <https://github.com/disposable-email-domains/disposable-email-domains>.
const DISPOSABLE_EMAIL_BLOCKLIST: &str =
include_str!("../../../assets/disposable_email_blocklist.txt");
pub fn config(cfg: &mut actix_web::web::ServiceConfig) {
cfg.service(
web::scope("/auth")
@@ -1816,11 +1820,22 @@ impl From<NewAccount> for AccountRegisterFlow {
}
}
/// Blacklist entries are matched literally, unless they begin with `*.`, in
/// which case they match any subdomain of the remaining suffix.
/// The bundled disposable domain list is checked first. Environment blacklist
/// entries are matched literally, unless they begin with `*.`, in which case
/// they match any subdomain of the remaining suffix.
fn is_blacklisted_domain(domain: &str) -> bool {
let domain = domain.to_ascii_lowercase();
if DISPOSABLE_EMAIL_BLOCKLIST.lines().any(|entry| {
// The upstream list expects listed domains to match subdomains too.
domain == entry
|| domain
.strip_suffix(entry)
.is_some_and(|subdomain| subdomain.ends_with('.'))
}) {
return true;
}
ENV.EMAIL_DOMAIN_BLACKLIST.iter().any(|entry| {
let entry = entry.trim().to_ascii_lowercase();