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 example.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 · ZWNJUsed 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.).
| Condition | Result |
|---|---|
| Preceded by Virama codepoint | Valid |
| Preceded by Dual/Right joining character AND followed by Dual/Left joining | Valid |
| At label start or end | Invalid (Chrome 148+) |
| Between Latin, Han, or other non-joining characters | Invalid (Chrome 148+) |
ZERO WIDTH JOINER
U+200D · ZWJUsed in Indic scripts to request a conjunct or ligature form. Valid in an IDN label only when preceded by a Virama codepoint.
| Condition | Result |
|---|---|
| Preceded by Virama codepoint | Valid |
| Any other position | Invalid (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
"example.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 ↗