← Chrome 148 reference

v148 · url · security · interop · shipped

IDNA ContextJ rules

Chrome 148 enforces IDNA2008's ContextJ rules when parsing URLs, disallowing the Zero Width Non-Joiner (U+200C) and Zero Width Joiner (U+200D) characters in most positions in internationalized domain names. This closes a homograph-attack vector and aligns Chrome with Firefox and Safari. Ships in Chrome 148 on all platforms.

at a glance

Shipped inChrome 148 (desktop, Android, WebView)
StatusEnabled by default
TypeSecurity / interoperability fix — no new API
ChromeStatus6295810820145152 — IDNA ContextJ rules

background: IDNA and ContextJ

Internationalized Domain Names in Applications (IDNA) defines how non-ASCII characters in domain names are encoded and validated. The URL Standard invokes IDNA processing with the CheckJoiners flag, which enables the ContextJ rules from IDNA2008/Unicode Technical Standard 46.

ContextJ rules restrict where the invisible formatting characters ZWNJ (U+200C, Zero Width Non-Joiner) and ZWJ (U+200D, Zero Width Joiner) may appear in domain labels. These characters are legitimate in scripts like Arabic and Indic where they affect shaping, but only in specific phonetically valid positions. Allowing them anywhere creates a security risk: a malicious domain can contain ZWJ/ZWNJ to produce a label that looks identical to a legitimate domain in a browser address bar.

Source: Unicode Technical Standard 46 — Unicode IDNA Compatibility Processing.

what changed in Chrome 148

Before Chrome 148, Chrome did not enforce ContextJ rules when parsing URLs. A URL containing ZWJ or ZWNJ in a domain label would be parsed and resolved without error — even in positions the IDNA specification disallows.

Chrome 148 passes the UIDNA_CHECK_CONTEXTJ option to ICU when processing domain labels. URLs that violate ContextJ rules are now treated as invalid:

Source: blink-dev Intent to Ship msg14721 and Chrome 148 release notes.

impact on web content

Legitimate content is not affected. ZWJ and ZWNJ in domain names are only valid in narrow phonological contexts within specific scripts; no correct internationalized domain name uses these characters in the positions that are now rejected.

Sites that constructed URLs programmatically with embedded invisible characters (intentionally or through encoding bugs) will receive a failure instead of a silently accepted URL. This is the intended behaviour.

// Before Chrome 148: silently accepted
// Chrome 148+: throws TypeError — ZWNJ disallowed in this position
try {
  const url = new URL('http://xn--‌nexample.com/');
} catch (e) {
  console.error('Invalid URL:', e.message);
}

browser support

Chrome / Edge148 (all platforms)
FirefoxShipped (enforces ContextJ rules)
SafariShipped (enforces ContextJ rules)
Source: chromestatus.com browser positions, May 2026.

see also