block-disposable-emails — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited block-disposable-emails (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
If anyone can sign up with any email, a chunk of your "users" will be throwaway inboxes — mailinator.com, 10minutemail.com, and hundreds more. They're how people farm free trials, dodge bans, and pad the numbers with accounts that never convert. Checking the signup domain against a community-maintained list of disposable domains takes minutes and cuts a surprising amount of junk.
Use the continuously-updated disposable/disposable-email-domains list (domains.json, tens of thousands of domains). Fetch it, cache for a day, load into a Set, and membership-test the domain after the @. A Set lookup is O(1); the daily cache means you're not hammering the CDN.
const LIST =
"https://rawcdn.githack.com/disposable/disposable-email-domains/master/domains.json";
let cache: Set<string> | null = null;
let fetchedAt = 0;
async function disposableDomains() {
if (cache && Date.now() - fetchedAt < 86_400_000) return cache; // 1 day
const res = await fetch(LIST);
cache = new Set<string>(await res.json());
fetchedAt = Date.now();
return cache;
}
export async function isDisposableEmail(email: string) {
const domain = email.split("@")[1]?.toLowerCase().trim();
if (!domain) return false;
return (await disposableDomains()).has(domain);
}Guard the signup handler:
if (await isDisposableEmail(email)) {
return new Response("Please use a permanent email address.", { status: 422 });
}check is trivially skipped — never trust it.
Workers, module-scope memory may not persist between requests; back the cache with KV (or similar) so you're not refetching the list constantly.
remember goes stale the day after you write it. The list doesn't.
a CAPTCHA (Cloudflare Turnstile / hCaptcha) stops bots before submit, the disposable-domain block stops throwaway humans, and a verification email at the end still requires a real, owned inbox. Each is minutes of work; together they compound.
From seangeng.com/writing/block-disposable-emails. Part of github.com/seangeng/skills. Credit: @venelinkochev.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.