Skip to content

Commit 6534e5b

Browse files
committed
fix(domain): match IDN TLDs against IANA list in IDNA-encoded form
With consider_tld=True, the TLD was looked up in the IANA list as written. The list stores internationalized TLDs in their ASCII (IDNA-encoded) form, so domains like пример.рф were rejected even though their punycode form xn--e1afmkfd.xn--p1ai was accepted. Encode the TLD before the lookup (falling back to the raw value when IDNA encoding fails, so unencodable TLDs are still rejected exactly like before). hostname() and url() pass consider_tld through to domain(), so they pick up the fix as well. Fixes #522 Co-authored-by: rahul05ranjan <11793455+rahul05ranjan@users.noreply.github.com>
1 parent 6ffd862 commit 6534e5b

2 files changed

Lines changed: 16 additions & 1 deletion

File tree

‎src/validators/domain.py‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,16 @@ def domain(
7676
if not value:
7777
return False
7878

79-
if consider_tld and not _IanaTLD.check(value.rstrip(".").rsplit(".", 1)[-1].upper()):
79+
tld = value.rstrip(".").rsplit(".", 1)[-1].upper()
80+
try:
81+
# IANA stores internationalized TLDs in their IDNA-encoded form
82+
# (e.g. "XN--P1AI"), so the lookup must use the encoded TLD too
83+
tld = tld.encode("idna").decode("utf-8").upper()
84+
except UnicodeError:
85+
# An unencodable TLD cannot be in the IANA list; keep the raw
86+
# value and let the lookup below reject it
87+
pass
88+
if consider_tld and not _IanaTLD.check(tld):
8089
return False
8190

8291
try:

‎tests/test_domain.py‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ def test_returns_true_on_valid_domain(value: str, rfc_1034: bool, rfc_2782: bool
4747
("example_.com", True, False, True),
4848
("somerandomexample.xn--fiqs8s", True, False, False),
4949
("somerandomexample.onion", True, False, False),
50+
# internationalized TLDs are matched via their IDNA-encoded form
51+
# ref: https://github.com/python-validators/validators/issues/522
52+
("пример.рф", True, False, False),
53+
("пример.рф.", True, True, False),
5054
],
5155
)
5256
def test_returns_true_on_valid_top_level_domain(
@@ -100,6 +104,8 @@ def test_returns_failed_validation_on_invalid_domain(value: str, rfc_1034: bool,
100104
("_example.#13", True, False, True),
101105
("example_.fo-ul", True, False, True),
102106
("somerandomexample.xn-n-fiqs8s", True, False, False),
107+
# non-IANA IDN TLDs must still be rejected after encoding
108+
("пример.испытание", True, False, False),
103109
],
104110
)
105111
def test_returns_failed_validation_invalid_top_level_domain(

0 commit comments

Comments
 (0)