Medium watch CVSS 4.3 chrome Spoofing 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
4.3
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUI misrepresentation in UrlFormatting
DescriptionUI misrepresentation in UrlFormatting
ComponentUrlFormatting
Bug ClassSpoofing
Action tierwatch — logic/policy bug — security-relevant, no memory-unsafety
Computed by PatchGap's deterministic exploitability ruler from the fixing commit. patch-now = RCE-class & attacker-reachable in a default config, or exploited in the wild; watch = real security signal below that bar; noise = no security relevance.
Tracker514069596
Fix commit7cc70a298354 (chromium/src) +21/-3
CWECWE-451
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:N
CISA KEVNot listed
CreditedGoogle
Reported2026-05-17 (per vendor advisory)
Fix landed2026-07-31 (public git)
Disclosed2026-09-08
Patch gap39 days — fix public in source before the advisory

Background

IDN (Internationalized Domain Name)
a domain name containing non-ASCII characters, encoded on the wire as ASCII xn-- Punycode but potentially displayed to the user as decoded Unicode.
`IDNSpoofChecker`
the Chrome component in components/url_formatter/spoof_checks/idn_spoof_checker.cc that decides whether a decoded Unicode label is safe to show, falling back to raw Punycode display when a label is deemed spoofy.
Dangerous-pattern regex
an icu::RegexMatcher (dangerous_pattern_) built from a large alternation of sub-patterns; if any label matches, the label is treated as unsafe and is not rendered as Unicode.
U+30FB (Katakana Middle Dot `・`)
a punctuation-like CJK character whose small centered dot visually resembles a . label separator, making it a spoofing risk outside genuine Japanese text.

Root Cause Analysis

The dangerous-pattern regex contained the sub-pattern R"([a-z]・|・[a-z]|)", which flagged U+30FB as spoofy only when it was directly adjacent to an ASCII lowercase letter. Because the alternation matched no other neighbors, a label placing U+30FB between digits, hyphens, or non-Japanese scripts (Cyrillic, Greek) — or at the very end of a label — did not match any dangerous pattern and was therefore decoded and displayed as Unicode. The intended invariant is that the middle dot may only appear in a real Japanese context (next to Hiragana, Katakana, or Han) so it cannot be mistaken for a separator, but the narrow [a-z] check enforced only a fraction of that invariant.

The fix replaces the two [a-z]-anchored alternatives with R"([^\p{scx=kana}\p{scx=hira}\p{scx=hani}]・|)", R"(・[^\p{scx=kana}\p{scx=hira}\p{scx=hani}]|)", and R"(・$|)", so U+30FB is rejected whenever either neighbor is outside Hiragana/Katakana/Han or when it terminates a label. This TIGHTENS the check: the regex now matches (and thus rejects) many more labels, forcing Punycode display for the previously-decoded spoofy cases.

Key insight
The single mistake was allow-listing by exclusion of one narrow class (ASCII lowercase) instead of requiring an explicit Japanese-script context, leaving digits, hyphens, other scripts, and end-of-label positions uncovered. The fix inverts the logic to a positive Script_Extensions requirement (scx=hira/kana/hani) plus an end-anchor, so any non-Japanese neighbor triggers rejection.

Attack Path

  1. Choose a deceptive label The attacker crafts a Unicode label that uses U+30FB between non-Japanese characters, e.g. 192・168・0・1 or a Cyrillic string, where the middle dots read as separators.
  2. Register/encode as Punycode The label is registered as its xn-- form (e.g. xn--19216801-rg5gdb.jp) so it is a valid hostname.
  3. Bypass the narrow check On display, IDNSpoofChecker runs the pre-patch regex; since neither neighbor of U+30FB is [a-z], no dangerous pattern matches and the label passes as safe.
  4. Unicode is shown in the omnibox Chrome decodes and displays the Unicode form, so the user sees middle dots that mimic dots/label boundaries, misrepresenting the true origin.
  5. User misjudges the site (inferred) Believing the URL to be a benign or trusted host (e.g. an IP-like or multi-label string), the user proceeds, enabling phishing or origin confusion.

Impact Assessment

An attacker gains UI misrepresentation of a hostname in the browser omnibox/URL display (renderer/browser UI context, no memory-safety implications), letting a decoded IDN label visually impersonate a separator-delimited name. The only precondition is that the victim navigates to (or is shown) an attacker-controlled IDN using U+30FB in a non-Japanese context. Severity is a spoofing/UI-misrepresentation issue as classified by the advisory; any resulting phishing or credential compromise is downstream and (inferred).

Files Changed

  • components/url_formatter/spoof_checks/idn_spoof_checker_unittest.cc
  • components/url_formatter/spoof_checks/idn_spoof_checker.cc

Audit Directions

  • Exclusion-based allow-lists
    Review spoof-check patterns that reject only one specific neighbor class (e.g. [a-z]) instead of positively requiring the legitimate context; other visually-confusable characters (U+30FC and similar) may have the same too-narrow guards.
  • Positional coverage
    Check that adjacency rules cover start-of-label, end-of-label, and both-sides cases, since the missing ・$ anchor shows end positions are easy to overlook.
  • Separator-lookalikes
    Enumerate Unicode code points that resemble ., /, or - (middle dots, ideographic separators, fullwidth punctuation) and verify each is context-restricted in dangerous_pattern_ rather than allowed by default.
From 7cc70a298354e451a224cdfbb3536dcfb83b7d96 Mon Sep 17 00:00:00 2001
From: Mustafa Emre Acer <[email protected]>
Date: Fri, 31 Jul 2026 12:29:36 -0700
Subject: [PATCH] IDN display: block U+30FB next to non-Japanese characters

The dangerous-pattern check for U+30FB (Katakana Middle Dot) only
rejected the character when the adjacent code point was an ASCII
lowercase letter. Labels where U+30FB sits between digits, hyphens,
or other non-Japanese characters were therefore decoded for display
even though the middle dot visually resembles a label separator.

Widen the check so that U+30FB is rejected when adjacent to any
character not in Hiragana, Katakana, or Han, or at the end of a
label. This prevents visual confusion with label separators in
non-Japanese contexts.

TAG=agy

Bug: 514069596
Change-Id: If25fd8442847c2a078674474c642279403d91c51
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8179732
Reviewed-by: Chris Thompson <[email protected]>
Commit-Queue: Mustafa Emre Acer <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1672019}
---
diff --git a/components/url_formatter/spoof_checks/idn_spoof_checker.cc b/components/url_formatter/spoof_checks/idn_spoof_checker.cc
index bf33238..bda0fcd 100644
--- a/components/url_formatter/spoof_checks/idn_spoof_checker.cc
+++ b/components/url_formatter/spoof_checks/idn_spoof_checker.cc
@@ -503,9 +503,14 @@
             R"(^[\p{scx=hira}]+[\u30d8-\u30da][\p{scx=hira}]+$|)"
 
             // Disallow U+30FB (Katakana Middle Dot) and U+30FC (Hiragana-
-            // Katakana Prolonged Sound) used out-of-context.
+            // Katakana Prolonged Sound) used out-of-context. U+30FB is
+            // rejected when adjacent to any character not in Hiragana,
+            // Katakana, or Han, or at the end of a label, to prevent
+            // visual confusion with label separators.
             R"([^\p{scx=kana}\p{scx=hira}]\u30fc|^\u30fc|)"
-            R"([a-z]\u30fb|\u30fb[a-z]|)"
+            R"([^\p{scx=kana}\p{scx=hira}\p{scx=hani}]\u30fb|)"
+            R"(\u30fb[^\p{scx=kana}\p{scx=hira}\p{scx=hani}]|)"
+            R"(\u30fb$|)"
 
             // Disallow these CJK ideographs and Kangxi Radicals if they are
             // next to non-CJK characters. These characters can be used to spoof
diff --git a/components/url_formatter/spoof_checks/idn_spoof_checker_unittest.cc b/components/url_formatter/spoof_checks/idn_spoof_checker_unittest.cc
index 7967c67..0e582a2 100644
--- a/components/url_formatter/spoof_checks/idn_spoof_checker_unittest.cc
+++ b/components/url_formatter/spoof_checks/idn_spoof_checker_unittest.cc
@@ -295,7 +295,8 @@
     // Latin + U+30FC + Latin
     {"xn--abcdef-r64e.jp", u"abc\u30fcdef.jp", kUnsafe},
 
-    // U+30FB (・) is not allowed next to Latin, but allowed otherwise.
+    // U+30FB (・) is allowed only when adjacent to Hiragana, Katakana, or Han,
+    // and not at the end of a label.
     // U+30FB + Han
     {"xn--vekt920a.jp", u"\u30fb\u91ce.jp", kSafe},
     // Han + U+30FB + Han
@@ -304,6 +305,18 @@
     {"xn--abcdef-k64e.jp", u"abc\u30fbdef.jp", kUnsafe},
     // U+30FB + Latin
     {"xn--abc-os4b.jp", u"\u30fbabc.jp", kUnsafe},
+    // digit + U+30FB + digit
+    {"xn--12-3n4a.jp", u"1\u30fb2.jp", kUnsafe},
+    // multiple digit + U+30FB groups
+    {"xn--19216801-rg5gdb.jp", u"192\u30fb168\u30fb0\u30fb1.jp", kUnsafe},
+    // hyphen + U+30FB + hyphen
+    {"xn--a--b-cx4c.jp", u"a-\u30fb-b.jp", kUnsafe},
+    // Cyrillic + U+30FB + Cyrillic
+    {"xn--80ac1155a.jp", u"\u0430\u30fb\u0431.jp", kUnsafe},
+    // Greek + U+30FB + Greek
+    {"xn--mxac2985a.jp", u"\u03b1\u30fb\u03b2.jp", kUnsafe},
+    // Han + U+30FB at the end of a label
+    {"xn--vek944n.jp", u"\u672c\u30fb.jp", kUnsafe},
 
     // U+30FD (ヽ) is allowed only after Katakana.
     // Katakana + U+30FD
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/components/url_formatter/spoof_checks/idn_spoof_checker_unittest.cc b/components/url_formatter/spoof_checks/idn_spoof_checker_unittest.cc
index 7967c67..0e582a2 100644
--- a/components/url_formatter/spoof_checks/idn_spoof_checker_unittest.cc
+++ b/components/url_formatter/spoof_checks/idn_spoof_checker_unittest.cc
@@ -295,7 +295,8 @@
     // Latin + U+30FC + Latin
     {"xn--abcdef-r64e.jp", u"abc\u30fcdef.jp", kUnsafe},
 
-    // U+30FB (・) is not allowed next to Latin, but allowed otherwise.
+    // U+30FB (・) is allowed only when adjacent to Hiragana, Katakana, or Han,
+    // and not at the end of a label.
     // U+30FB + Han
     {"xn--vekt920a.jp", u"\u30fb\u91ce.jp", kSafe},
     // Han + U+30FB + Han
@@ -304,6 +305,18 @@
     {"xn--abcdef-k64e.jp", u"abc\u30fbdef.jp", kUnsafe},
     // U+30FB + Latin
     {"xn--abc-os4b.jp", u"\u30fbabc.jp", kUnsafe},
+    // digit + U+30FB + digit
+    {"xn--12-3n4a.jp", u"1\u30fb2.jp", kUnsafe},
+    // multiple digit + U+30FB groups
+    {"xn--19216801-rg5gdb.jp", u"192\u30fb168\u30fb0\u30fb1.jp", kUnsafe},
+    // hyphen + U+30FB + hyphen
+    {"xn--a--b-cx4c.jp", u"a-\u30fb-b.jp", kUnsafe},
+    // Cyrillic + U+30FB + Cyrillic
+    {"xn--80ac1155a.jp", u"\u0430\u30fb\u0431.jp", kUnsafe},
+    // Greek + U+30FB + Greek
+    {"xn--mxac2985a.jp", u"\u03b1\u30fb\u03b2.jp", kUnsafe},
+    // Han + U+30FB at the end of a label
+    {"xn--vek944n.jp", u"\u672c\u30fb.jp", kUnsafe},
 
     // U+30FD (ヽ) is allowed only after Katakana.
     // Katakana + U+30FD
Loading diff…

Original Bug Report

reported by [email protected]

Label-boundary spoofing via U+30FB (Katakana Middle Dot) adjacent to digits

Project Fortify, an experimental security project, has identified the following potential security issue. If you’re a feature owner CC-ed on this bug, please do your best to review these reports. Please see https://chromium.googlesource.com/chromium/src/+/main/docs/security/ai-generated-security-bugs-faq.md for more information.

Overview: A logic gap in the IDN spoof checker allows the Katakana Middle Dot (U+30FB) to be displayed in Unicode when adjacent to digits or hyphens, despite its visual resemblance to a label separator. This could allow an attacker to craft domain labels that visually mimic IP addresses or subdomains in the Omnibox.

Affected files:

  • components/url_formatter/spoof_checks/idn_spoof_checker.cc
  • components/url_formatter/url_formatter.cc
  • components/url_formatter/spoof_checks/idn_spoof_checker_unittest.cc

Estimated timestamp from git blame: Unknown (Google3 checkout)

Summary

A potential vulnerability exists in IDNSpoofChecker::SafeToDisplayAsUnicode where the Katakana Middle Dot (U+30FB, ・) is insufficiently restricted. This character visually resembles a standard dot (.) used as a DNS label separator. While Chrome attempts to block its use ‘out-of-context’, the current implementation only triggers a warning if the character is adjacent to lowercase ASCII letters, failing to account for cases where it is flanked by digits or hyphens.

Technical Details

In components/url_formatter/spoof_checks/idn_spoof_checker.cc, the dangerous_pattern regex used to identify unsafe uses of the Katakana Middle Dot is defined as:

// components/url_formatter/spoof_checks/idn_spoof_checker.cc:508
R"([a-z]\u30fb|\u30fb[a-z]|)"

This regex is too narrow. It allows U+30FB to be displayed in Unicode if it is surrounded by digits ([0-9]) or hyphens (-).

Furthermore, Chrome’s initialization of the ICU UIDNA object in components/url_formatter/url_formatter.cc does not include the UIDNA_CHECK_CONTEXTO flag:

// components/url_formatter/url_formatter.cc:435
value = uidna_openUTS46(UIDNA_CHECK_BIDI, &err);

Without this flag, ICU does not enforce Unicode’s contextual rules for U+30FB, which require it to be surrounded by Japanese scripts (Katakana, Hiragana, or Han). As a result, the check falls back to the flawed regex in IDNSpoofChecker, which permits the character in numeric contexts.

Potential Impact

An attacker can register a domain with a Punycode label that decodes to a string using U+30FB between digits. This label will be displayed in Unicode in the Omnibox and Page Info bubble, appearing as multiple labels.

For example:

  • xn--19216801-rg5gdb.attacker.com could render as 192・168・0・1.attacker.com, mimicking an internal IP address.
  • xn--v10-qs4b.example.com could render as v1・0.example.com, mimicking a versioned subdomain.

Suggested Potential Reproduction Steps

  1. Identify a target spoofing structure using digits and middle dots (e.g., 192・168・0・1).
  2. Convert this string to a Punycode label (e.g., xn--19216801-rg5gdb).
  3. Register a domain name containing this label under an attacker-controlled TLD.
  4. Navigate to the URL in Chrome and observe that the Omnibox displays the middle dots in Unicode, creating a visual label-boundary spoof.

(Note: These are potential steps as our analysis is based on code review.)

Update the dangerous_pattern regex in idn_spoof_checker.cc to be more restrictive. Ideally, U+30FB should only be permitted when both the preceding and following characters belong to a Japanese script (Katakana, Hiragana, or Han). Additionally, consider enabling the UIDNA_CHECK_CONTEXTO flag in url_formatter.cc to align with Unicode’s recommended safety checks.

Evaluated with Chrome root at commit: 1a8d40fc44df2088d5945c0bf53584038aa1614a


Results so far have been promising, but there can be wrong deductions. Feel free to adjust as follows:

  • If you are familiar with the severity guidelines, you may adjust the severity.
  • If this is a false positive, and there’s no work to be done, please close as WAI.
  • If there is work to do here but not a vulnerability, please change the issue type to Task/Bug/FR.

Data from false positives will be used to improve accuracy over time. And please feel free to reach out to me directly if you have concerns or feedback on the project.

View on issue tracker