v148 · Security · Rule Reference

Rule Reference

The IDNA2008 ContextJ rules, the Unicode joining categories they reference, and why invisible joiners in domain names are a security concern.

security motivation

IDN homograph attacks

Invisible characters like ZWJ and ZWNJ look identical to nothing — the human eye cannot distinguish example.com from exam‍ple.com (which has a ZWJ inside). Without ContextJ enforcement, an attacker could register a domain that is visually identical to a legitimate one but resolves to a different IP. Chrome 148's stricter validation rejects joining characters in contexts where they have no linguistic purpose — closing this spoofing vector.

ContextJ characters

ZERO WIDTH NON-JOINER

U+200C · ZWNJ

Used in Arabic, Persian, and Indic scripts to prevent ligature formation. Valid in an IDN label only when preceded by a character with a joining type of Dual_Joining or Right_Joining (Arabic/Syriac), OR when it follows a Virama (combining character used in Devanagari, Malayalam, etc.).

ConditionResult
Preceded by Virama codepointValid
Preceded by Dual/Right joining character AND followed by Dual/Left joiningValid
At label start or endInvalid (Chrome 148+)
Between Latin, Han, or other non-joining charactersInvalid (Chrome 148+)

ZERO WIDTH JOINER

U+200D · ZWJ

Used in Indic scripts to request a conjunct or ligature form. Valid in an IDN label only when preceded by a Virama codepoint.

ConditionResult
Preceded by Virama codepointValid
Any other positionInvalid (Chrome 148+)

Unicode joining categories

Joining type Abbreviation Scripts
Dual_Joining D Arabic, Syriac — joins to both left and right
Right_Joining R Arabic — joins to the right only
Left_Joining L Some extended Arabic — joins to the left only
Non_Joining U Latin, Han, Greek — no joining behaviour
Transparent T Diacritics — transparent to joining context

valid vs invalid examples

// ✓ Valid — ZWNJ after Virama in Devanagari
"क‌ = ka + ZWNJ" — permitted: Virama context

// ✓ Valid — ZWNJ between Arabic dual-joining characters
"ع‌ب" — alef (right-joining) + ZWNJ + ba (dual-joining) — permitted

// ✗ Invalid — ZWJ between Latin characters
"exam‍ple.com" — no Virama precedes ZWJ

// ✗ Invalid — ZWNJ at label start
"‌example.com" — no preceding context

// ✗ Invalid — ZWNJ between CJK characters
"例‌子.com" — CJK has Non_Joining type

see also

scenario focus

Select a scenario to focus its rendered example and summary.

implementation reference

Need the exact API surface, compatibility boundaries, errors, lifecycle, and source links? Read the matching gendn reference ↗