Skip to content

Commit f72581c

Browse files
authored
Custom domain: don't allow external domain (#11064)
We have a CNAME from our external domain to readthedocs.io, making these domains valid if they are added to a project. This isn't a security issue, since our code won't resolve those domains because custom domains are checked last, and we have this protection in place: https://github.com/readthedocs/readthedocs.org/blob/7daff3d6cc953898934cc80cba53403d6e0fa259/readthedocs/core/unresolver.py#L590-L594
1 parent 12c90eb commit f72581c

File tree

2 files changed

+21
-2
lines changed

2 files changed

+21
-2
lines changed

readthedocs/projects/forms.py

+9-2
Original file line numberDiff line numberDiff line change
@@ -818,8 +818,15 @@ def clean_domain(self):
818818

819819
domain_string = parsed.netloc
820820

821-
# Don't allow production or public domain to be set as custom domain
822-
for invalid_domain in [settings.PRODUCTION_DOMAIN, settings.PUBLIC_DOMAIN]:
821+
# Don't allow internal domains to be added, we have:
822+
# - Dashboard domain
823+
# - Public domain (from where documentation pages are served)
824+
# - External version domain (from where PR previews are served)
825+
for invalid_domain in [
826+
settings.PRODUCTION_DOMAIN,
827+
settings.PUBLIC_DOMAIN,
828+
settings.RTD_EXTERNAL_VERSION_DOMAIN,
829+
]:
823830
if invalid_domain and domain_string.endswith(invalid_domain):
824831
raise forms.ValidationError(
825832
f'{invalid_domain} is not a valid domain.'

readthedocs/rtd_tests/tests/test_domains.py

+12
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,18 @@ def test_public_domain_not_allowed(self):
9292
f"{settings.PUBLIC_DOMAIN} is not a valid domain.",
9393
)
9494

95+
@override_settings(RTD_EXTERNAL_VERSION_DOMAIN="readthedocs.build")
96+
def test_external_domain_not_allowed(self):
97+
for domain in ["readthedocs.build", "test.readthedocs.build"]:
98+
form = DomainForm(
99+
{"domain": domain},
100+
project=self.project,
101+
)
102+
self.assertFalse(form.is_valid())
103+
self.assertEqual(
104+
form.errors["domain"][0], "readthedocs.build is not a valid domain."
105+
)
106+
95107
def test_domain_with_path(self):
96108
form = DomainForm(
97109
{"domain": "domain.com/foo/bar"},

0 commit comments

Comments
 (0)