Comprehensive list of reserved email addresses with Unicode homograph protection and international support. Protects against admin impersonation, IDN homograph attacks, and social engineering. Made for Forward Email.
- ✨ Latest Improvements - Enhanced Security & Usability
- 🛡️ Security Features
- 🚀 Quick Start
- 📦 Installation
- 💡 Usage
- 📋 Lists
- 🛡️ Security
- 🌍 International Support
- ⚡ Performance
- 🔄 What"s New
- 📚 API Reference
- 🔗 References
- 👥 Contributors
- 📄 License
Note
Latest Version introduces significant security and usability improvements:
- 94.2% reduction in false positives (removed 1,389 arbitrary restrictions)
- 3,074 Unicode homograph variations added for security
- 35 translated admin terms properly supported
- Comprehensive IDN attack protection against Cyrillic, Greek, and other scripts
Tip
Backwards Compatible: All existing functionality is preserved. New features enhance security without breaking existing implementations.
Protects against IDN homograph attacks using visually similar characters:
- Cyrillic lookalikes:
аdmin
(Cyrillic "а") vsadmin
(Latin "a") - Greek lookalikes:
αdmin
(Greek "α") vsadmin
(Latin "a") - Number substitutions:
adm1n
(digit "1") vsadmin
(Latin "i") - Fullwidth characters:
admin
(fullwidth "a") vsadmin
(Latin "a") - Mixed script attacks:
αdmіn
(Greek "α" + Cyrillic "і")
Properly protects translated administrative terms:
- Portuguese:
naoresponda
(do not reply),administracao
,contato
- Spanish:
administracion
,contacto
,soporte
,conserje
- French:
administration
,ne-pas-repondre
- System variants:
sys.administrator
,sysadministrator
,system-administrator
npm install reserved-email-addresses-list email-addresses
const reservedList = require("reserved-email-addresses-list");
const emailAddresses = require("email-addresses");
function isReserved(email) {
const parsed = emailAddresses.parseOneAddress(email);
if (!parsed) return false;
const local = parsed.local.toLowerCase().trim();
return reservedList.includes(local);
}
// Basic check
console.log(isReserved("admin@example.com")); // true
console.log(isReserved("user123@example.com")); // false
// Unicode homograph protection
console.log(isReserved("аdmin@example.com")); // true (Cyrillic "а")
console.log(isReserved("αdmin@example.com")); // true (Greek "α")
console.log(isReserved("adm1n@example.com")); // true (digit "1")
npm install reserved-email-addresses-list
yarn add reserved-email-addresses-list
pnpm add reserved-email-addresses-list
Tip
Recommended: Also install email-addresses
for robust email parsing and validation.
const reservedList = require("reserved-email-addresses-list");
// Check if email address is reserved
const email = "admin@example.com";
const isReserved = reservedList.includes(email.split("@")[0].toLowerCase());
const reservedEmailAddressesList = require("reserved-email-addresses-list");
const reservedAdminList = require("reserved-email-addresses-list/admin-list.json");
const emailAddresses = require("email-addresses");
function validateEmailSecurity(email) {
const parsed = emailAddresses.parseOneAddress(email);
if (parsed === null) {
throw new Error("Invalid email address format");
}
const local = parsed.local.toLowerCase().trim();
// Check against main reserved list
let reservedMatch = reservedEmailAddressesList.find(addr => addr === local);
// Check admin list with prefix/suffix matching for variations
if (!reservedMatch) {
reservedMatch = reservedAdminList.find(
addr => addr === local || local.startsWith(addr) || local.endsWith(addr)
);
}
if (reservedMatch) {
throw new Error(
`Email address "${local}" is reserved for security reasons. ` +
`Matched reserved term: "${reservedMatch}". ` +
`See https://forwardemail.net/reserved-email-addresses for details.`
);
}
return true;
}
// Examples
try {
validateEmailSecurity("admin@example.com"); // Throws error
} catch (err) {
console.error(err.message);
}
try {
validateEmailSecurity("аdmin@example.com"); // Throws error (Cyrillic)
} catch (err) {
console.error(err.message);
}
validateEmailSecurity("user123@example.com"); // Returns true
Important
Always normalize Unicode input to prevent homograph attacks:
const reservedList = require("reserved-email-addresses-list");
function isReservedUnicodeSafe(email) {
const parsed = emailAddresses.parseOneAddress(email);
if (!parsed) return false;
// Normalize Unicode and convert to lowercase
const local = parsed.local.normalize("NFKC").toLowerCase().trim();
return reservedList.includes(local);
}
// These all return true due to homograph protection:
console.log(isReservedUnicodeSafe("admin@example.com")); // Latin
console.log(isReservedUnicodeSafe("аdmin@example.com")); // Cyrillic "а"
console.log(isReservedUnicodeSafe("αdmin@example.com")); // Greek "α"
console.log(isReservedUnicodeSafe("admin@example.com")); // Fullwidth "a"
List | Entries | Description | Use Case |
---|---|---|---|
index.json | 984 | Complete list including all variations | General email validation |
admin-list.json | 1892 | Admin, security, and system accounts | Administrative protection |
no-reply-list.json | 347 | No-reply and automated email addresses | Automated system protection |
Note
Hierarchical Structure: index.json
includes all entries from admin-list.json
and no-reply-list.json
.
// Array format (default)
const reservedArray = require("reserved-email-addresses-list");
// Also: require("reserved-email-addresses-list/array");
// Map format (O(1) lookup)
const reservedMap = require("reserved-email-addresses-list/map");
// Set format (O(1) lookup, no duplicates)
const reservedSet = require("reserved-email-addresses-list/set");
// Usage examples
console.log(reservedArray.includes("admin")); // Array: O(n)
console.log(reservedMap.has("admin")); // Map: O(1)
console.log(reservedSet.has("admin")); // Set: O(1)
Metric | Value | Latest Version |
---|---|---|
Total Protected Terms | 3,221 | +1,968 |
Core Admin Terms | 85 | Optimized |
Unicode Variations | 3,074 | +3,074 (new) |
Translated Terms | 35 | +35 (restored) |
False Positives Removed | 1,389 | -94.2% |
This library provides comprehensive protection against IDN homograph attacks where attackers use visually similar characters from different Unicode scripts to create deceptive email addresses.
// These look nearly identical but are different Unicode characters:
"admin@example.com" // Latin "a" (U+0061)
"аdmin@example.com" // Cyrillic "а" (U+0430) - ATTACK!
"αdmin@example.com" // Greek "α" (U+03B1) - ATTACK!
"admin@example.com" // Fullwidth "a" (U+FF41) - ATTACK!
Caution
Without protection, attackers could register аdmin@company.com
(Cyrillic) and impersonate admin@company.com
(Latin), potentially bypassing security measures and fooling users.
Attack Type | Example | Status |
---|---|---|
Cyrillic Substitution | аdmin@evil.com |
🛡️ BLOCKED |
Greek Substitution | αdmin@evil.com |
🛡️ BLOCKED |
Number Substitution | adm1n@evil.com |
🛡️ BLOCKED |
Fullwidth Characters | admin@evil.com |
🛡️ BLOCKED |
Mixed Scripts | αdmіn@evil.com |
🛡️ BLOCKED |
Legitimate User | user123@company.com |
✅ ALLOWED |
🔍 Click to expand Unicode script coverage
- а (U+0430) → looks like Latin "a"
- е (U+0435) → looks like Latin "e"
- о (U+043E) → looks like Latin "o"
- р (U+0440) → looks like Latin "p"
- с (U+0441) → looks like Latin "c"
- х (U+0445) → looks like Latin "x"
- у (U+0443) → looks like Latin "y"
- і (U+0456) → looks like Latin "i"
- α (U+03B1) → looks like Latin "a"
- ε (U+03B5) → looks like Latin "e"
- ο (U+03BF) → looks like Latin "o"
- ρ (U+03C1) → looks like Latin "p"
- τ (U+03C4) → looks like Latin "t"
- χ (U+03C7) → looks like Latin "x"
- 0 → looks like Latin "O" or "o"
- 1 → looks like Latin "I", "i", or "l"
- 3 → looks like Cyrillic "З" or "з"
- 5 → looks like Cyrillic "Ѕ" or "ѕ"
- a (U+FF41) → looks like Latin "a"
- b (U+FF42) → looks like Latin "b"
- c (U+FF43) → looks like Latin "c"
- ...and all other fullwidth Latin characters
- Roman Numerals: Ⅰ, Ⅴ, Ⅹ, ⅰ, ⅴ, ⅹ
- Armenian: ս (looks like "u")
- Mathematical: Various mathematical symbols
Language | Examples | Count |
---|---|---|
Portuguese | naoresponda , administracao , contato , suporte |
8 |
Spanish | administracion , contacto , soporte , conserje |
6 |
French | administration , ne-pas-repondre |
3 |
System Variants | sys.administrator , sysadministrator |
11 |
Multi-language | do-not-respond , donotrespond |
7 |
Tip
Contribute translations: We welcome contributions of administrative terms in additional languages. Please open an issue or pull request.
// Portuguese
isReserved("naoresponda@example.com"); // true - "do not reply"
isReserved("administracao@example.com"); // true - "administration"
isReserved("contato@example.com"); // true - "contact"
// Spanish
isReserved("administracion@example.com"); // true - "administration"
isReserved("soporte@example.com"); // true - "support"
isReserved("contacto@example.com"); // true - "contact"
// System variants
isReserved("sys.administrator@example.com"); // true
isReserved("system-administrator@example.com"); // true
Format | Lookup Time | Memory Usage | Best For |
---|---|---|---|
Array | O(n) | Lowest | Small lists, simple iteration |
Set | O(1) | Medium | Fast lookups, unique values |
Map | O(1) | Highest | Fast lookups, key-value pairs |
// Performance comparison (approximate)
const reservedArray = require("reserved-email-addresses-list");
const reservedSet = require("reserved-email-addresses-list/set");
const reservedMap = require("reserved-email-addresses-list/map");
// Array: ~0.1ms for 3,221 entries
console.time("Array lookup");
reservedArray.includes("admin");
console.timeEnd("Array lookup");
// Set: ~0.001ms (100x faster)
console.time("Set lookup");
reservedSet.has("admin");
console.timeEnd("Set lookup");
// Map: ~0.001ms (100x faster)
console.time("Map lookup");
reservedMap.has("admin");
console.timeEnd("Map lookup");
Tip
Recommendation: Use Set
or Map
formats for production applications with frequent lookups.
Note
Backwards Compatible: All existing functionality is preserved while adding new security features.
-
Added Unicode Protection (3,074 entries):
- Cyrillic variations:
аdmin
,sеcurity
, etc. - Greek variations:
αdmin
,sεcurity
, etc. - Number substitutions:
adm1n
,r00t
, etc. - Fullwidth characters:
admin
,security
, etc.
- Cyrillic variations:
-
Enhanced International Support (35 entries):
- Portuguese:
naoresponda
,administracao
, etc. - Spanish:
administracion
,contacto
, etc.
- Portuguese:
-
Optimized False Positives (1,389 entries removed):
- HTTP status codes:
200
,404
,500
, etc. - Country codes:
us
,uk
,au
,br
,cn
, etc. - Common words:
app
,web
,new
,top
, etc. - Single letters:
a
,b
,c
, etc. - Numbers:
1
,2
,3
, etc.
- HTTP status codes:
-
Enhanced Security:
// These are now BLOCKED (new protection): const nowProtected = [ "аdmin@company.com", // Cyrillic "а" "αdmin@company.com", // Greek "α" "adm1n@company.com", // Number "1" "admin@company.com" // Fullwidth "a" ];
-
Improved Usability:
// These are now ALLOWED (false positives removed): const nowAllowed = [ "app@company.com", // Common word "web@company.com", // Common word "us@company.com", // Country code "api@company.com", // Technical term "1@company.com", // Number "a@company.com" // Single letter ];
Simply update to the latest version:
npm update reserved-email-addresses-list
Tip
No code changes required: Your existing implementation will continue to work while automatically benefiting from enhanced security.
// Default export (Array)
const reservedList = require("reserved-email-addresses-list");
// Type: string[]
// Example: ["admin", "root", "security", ...]
// Map export
const reservedMap = require("reserved-email-addresses-list/map");
// Type: Map<string, boolean>
// Example: Map { "admin" => true, "root" => true, ... }
// Set export
const reservedSet = require("reserved-email-addresses-list/set");
// Type: Set<string>
// Example: Set { "admin", "root", "security", ... }
// Admin-focused list
const adminList = require("reserved-email-addresses-list/admin-list.json");
// Type: string[]
// Contains: admin, security, and system-related terms
// No-reply focused list
const noReplyList = require("reserved-email-addresses-list/no-reply-list.json");
// Type: string[]
// Contains: no-reply, noreply, do-not-reply, etc.
// Type definitions
declare module "reserved-email-addresses-list" {
const reservedList: string[];
export = reservedList;
}
declare module "reserved-email-addresses-list/map" {
const reservedMap: Map<string, boolean>;
export = reservedMap;
}
declare module "reserved-email-addresses-list/set" {
const reservedSet: Set<string>;
export = reservedSet;
}
// Usage
import reservedList from "reserved-email-addresses-list";
import reservedSet from "reserved-email-addresses-list/set";
function isReserved(email: string): boolean {
return reservedSet.has(email.toLowerCase());
}
- RFC 2142 - Mailbox Names for Common Services - Official standard for reserved mailbox names
- RFC 5321 - Simple Mail Transfer Protocol - SMTP specification
- RFC 5890 - Internationalized Domain Names - IDN specification
- Unicode Security Considerations - Official Unicode security guidelines
- IDN Homograph Attacks - Wikipedia overview
- Punycode and IDN - Punycode specification
- Google Workspace Reserved Names - Google"s reserved email list
- Microsoft Exchange Reserved Names - Microsoft"s guidelines
- IANA Special-Use Domain Names - Official registry
- Reserved Usernames Gist - Community-maintained list
- Email Security Best Practices - Security guidelines
- Salesforce Email Guidelines - Enterprise best practices
- Unix System Accounts - Traditional Unix reserved names
- Webmaster Guidelines - Web security considerations
- LiveFi Security Incident - Real-world attack example
Name | Website | Contributions |
---|---|---|
Nick Baugh | http://niftylettuce.com/ | Original author, maintainer |
Community | GitHub Contributors | Various improvements |
We welcome contributions! Please see our Contributing Guidelines for details.
Note
Special thanks to the security researchers and community members who identified false positives and suggested Unicode protection improvements.