[B]

A Stronger Username and Password Regex

While setting up a Grav CMS website, a stronger username and password regex was in order. The username default regex for the installation is ^[a-z0-9_-]{3,16}$ all lower case letters, digits, dashes, underscores, and must be 3–16 characters. The default password regex is (?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,} one number, one upper case, one lower case, and 8 or more characters.

Username: ^[a-z0-9_-]{3,16}$
Password: (?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}

The defaults are simply unacceptable. Too many websites are being hacked, and making a stronger regex is a simple way to make it harder to for the basement hacker to crack.

So, I did a bit of research, fed my requirements into my handy know-it-all (AI), tested it out, and voilà — a shinny new regex is born. 🙂

The Final Regex Code

Username:

^[a-z][a-z0-9_-]{4,16}$

Password:

^[a-z](?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?!.*(.)(\1))(?!.*0[oO]|.*[oO]0)(?!.*1[lLI]|.*[lLI]1)(?!.*5[sS]|.*[sS]5)(?!.*2[zZ]|.*[zZ]2)(?!.*8[bB]|.*[bB]8)(?!.*6[gG]|.*[gG]6)(?!.*9[gG]|.*[gG]9)(?!.*c[CƆ]|.*[CƆ]c)(?!.*a[@A]|.*[@A]a)(?!.*m.rn|.*rn.*m).{11,}$

The only difference in the regex codes above is the username must be 5–15 characters long, and the password must be at least 12 characters.

And for all the code junkies out there who stumble across this post, here are the technical bits:

Regex Breakdown

Username Regex:

^[a-z][a-z0-9_-]{2,15}$

ComponentPurpose
^Start of string anchor
[a-z]Username must start with a lowercase letter
[a-z0-9_-]{2,15}Remaining characters must be lowercase letters, digits, underscores, or dashes
Ensures total length is 3–16 characters
$End of string anchor

Password Regex:

^[a-z](?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?!.*(.)(\1))(?!.*0[oO]|.*[oO]0)(?!.*1[lLI]|.*[lLI]1)(?!.*5[sS]|.*[sS]5)(?!.*2[zZ]|.*[zZ]2)(?!.*8[bB]|.*[bB]8)(?!.*6[gG]|.*[gG]6)(?!.*9[gG]|.*[gG]9)(?!.*c[CƆ]|.*[CƆ]c)(?!.*a[@A]|.*[@A]a)(?!.*m.rn|.*rn.*m).{11,}$

ComponentPurpose
^Start of string
[a-z]Password must start with a lowercase letter
(?=.*[a-z])Requires at least one lowercase character
(?=.*[A-Z])Requires at least one uppercase character
(?=.*\d)Requires at least one number
(?!.*(.)(\1))No identical consecutive characters
Confusable (homoglyph) detection
(?!.*0[oO]|.*[oO]0)Forbid 0 with o/O
(?!.*1[lLI]|.*[lLI]1)Forbid 1 with l/L/I
(?!.*5[sS]|.*[sS]5)Forbid 5 with s/S
(?!.*2[zZ]|.*[zZ]2)Forbid 2 with z/Z
(?!.*8[bB]|.*[bB]8)Forbid 8 with b/B
(?!.*6[gG]|.*[gG]6)Forbid 6 with g/G
(?!.*9[gG]|.*[gG]9)Forbid 9 with g/G
(?!.*c[CƆ]|.*[CƆ]c)Forbid c with C/Ɔ
(?!.*a[@A]|.*[@A]a)Forbid a with A/@
(?!.*m.rn|.*rn.*m)Special case: forbid m next to homoglyph sequence rn
.{11,}After consuming the first letter, require ≥11 more characters → total length ≥12
$End of string

Homoglyph Pairs Covered

Homoglyph PairRule
0 / o / O(?!.*0[oO]|.*[oO]0)
1 / l / L / I(?!.*1[lLI]|.*[lLI]1)
5 / s / S(?!.*5[sS]|.*[sS]5)
2 / z / Z(?!.*2[zZ]|.*[zZ]2)
8 / b / B(?!.*8[bB]|.*[bB]8)
6 / g / G(?!.*6[gG]|.*[gG]6)
9 / g / G(?!.*9[gG]|.*[gG]9)
c / C / Ɔ(?!.*c[CƆ]|.*[CƆ]c)
a / A / @(?!.*a[@A]|.*[@A]a)
m / rn(?!.*m.rn|.*rn.*m)

Test Cases

InputResultReason
john_doe✅ MATCHValid username
abc123✅ MATCHValid username
a-b_c✅ MATCHValid username
ab❌ NO MATCHToo short (<3 chars)
Aabc❌ NO MATCHMust start with lowercase
aPassword123456✅ MATCHValid password
aA1bcdefghijk✅ MATCHMeets all password rules
aAA1bbbbbbbb❌ NO MATCHConsecutive repeated characters
aPassword000❌ NO MATCHContains 0 and o
apP1mRnsecure❌ NO MATCHContains both m and rn

Summary

Username Regex Enforces:

1. Starts with a lowercase letter
2. Contains only lowercase letters, digits, underscores, and dashes
3. Total length 3–16
4. No homoglyph or repetition checks (not needed)

Password Regex Enforces:

1. Starts with a lowercase letter
2. Contains uppercase, lowercase, and digits
3. 12+ characters long
4. No identical consecutive characters
5. Homoglyph/confusable pairs disallowed
6. m/rn visual‑collision disallowed

Comments

Leave a Reply