Validate origin hostname shape: no empty labels (leading/trailing/double dots rejected) in stored config, sanitize, and Passkey construction

This commit is contained in:
2026-09-07 16:50:40 +00:00
parent 04d6768ba6
commit cb609abe5f
4 changed files with 67 additions and 6 deletions
+44
View File
@@ -222,6 +222,20 @@ class TestValidateConfig:
Config(domains={"a.com": DomainConfig(origins={"*": True})})
)
def test_malformed_origin_hostname_rejected(self):
"""No empty hostname labels — leading, trailing and double dots
are invalid, in concrete entries and wildcard bases alike."""
for key in (".a.com", "a..com", "a.com.", "http://.a.com:8080"):
with pytest.raises(ValueError, match="Invalid origin"):
domains.validate_config(
Config(domains={"a.com": DomainConfig(origins={key: True})})
)
for key in ("*..a.com", "**..a.com"):
with pytest.raises(ValueError, match="Invalid wildcard origin"):
domains.validate_config(
Config(domains={"a.com": DomainConfig(origins={key: True})})
)
def test_subdomain_entry_is_in_domain(self):
"""An entry within the rp-id domain is an ordinary in-domain
sign-in site, never a related origin."""
@@ -395,6 +409,27 @@ class TestSanitizeConfig:
assert config.domains["a.com"].origins == {}
assert warnings
def test_malformed_hostname_dropped(self):
"""Empty hostname labels (leading/trailing/double dots) are dropped,
from concrete entries and wildcard bases alike."""
config, warnings = domains.sanitize_config(
Config(
domains={
"a.com": DomainConfig(
origins={
".a.com": True,
"a.com.": True,
"**.a..com": True,
"ok.a.com": True,
}
)
}
)
)
assert list(config.domains["a.com"].origins) == ["ok.a.com"]
assert len(warnings) == 3
domains.validate_config(config) # sanitized config is strict-clean
def test_invalid_rp_id_domain_dropped(self):
config, warnings = domains.sanitize_config(
Config(domains={"not a domain!": DomainConfig(), "ok.com": DomainConfig()})
@@ -558,6 +593,15 @@ class TestOriginValidation:
with pytest.raises(ValueError, match="Invalid origin"):
Passkey(rp_id="example.com", origins=["*"])
def test_malformed_hostname_rejected(self):
"""Leading/trailing/double dots are invalid in any entry form."""
with pytest.raises(ValueError, match="malformed hostname"):
Passkey(rp_id="example.com", origins=["https://.example.com"])
with pytest.raises(ValueError, match="malformed hostname"):
Passkey(rp_id="example.com", origins=["**.a..example.com"])
with pytest.raises(ValueError, match="malformed hostname"):
Passkey(rp_id="example.com", related_origins=["https://other..com"])
def test_localhost_wildcard_matches_any_scheme_and_port(self):
"""Under localhost, wildcards match any scheme and any port."""
p = Passkey(rp_id="localhost", origins=["**.localhost"])