Skip to content

Commit 01f96f1

Browse files
committed
Validate the header value before injecting it
1 parent 9b46d69 commit 01f96f1

File tree

2 files changed

+19
-6
lines changed

2 files changed

+19
-6
lines changed

readthedocs/proxito/middleware.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
)
1616
from django.conf import settings
1717
from django.core.exceptions import SuspiciousOperation
18+
from django.http.response import BadHeaderError, ResponseHeaders
1819
from django.shortcuts import redirect
1920
from django.urls import reverse
2021
from django.utils.deprecation import MiddlewareMixin
@@ -369,14 +370,25 @@ def _get_https_redirect(self, request):
369370
return None
370371

371372
def add_resolver_headers(self, request, response):
372-
# TODO: find a better way to re-use the unresolved URL so we don't
373-
# query the db multiple times on the same request.
374-
# https://github.com/readthedocs/readthedocs.org/issues/10456
375373
if hasattr(request, "unresolved_url") and request.unresolved_url is not None:
376374
# TODO: add more ``X-RTD-Resolver-*`` headers
377-
response["X-RTD-Resolver-Filename"] = escape(
378-
request.unresolved_url.filename
379-
)
375+
header_value = escape(request.unresolved_url.filename)
376+
try:
377+
# Use Django internals to validate the header's value before injecting it.
378+
ResponseHeaders({})._convert_to_charset(
379+
header_value,
380+
"latin-1",
381+
mime_encode=True,
382+
)
383+
384+
response["X-RTD-Resolver-Filename"] = header_value
385+
except BadHeaderError:
386+
# Skip adding the header because it fails validation
387+
log.info(
388+
"Skip adding X-RTD-Resolver-Filename header due to invalid value.",
389+
filename=request.unresolved_url.filename,
390+
value=header_value,
391+
)
380392

381393
def process_response(self, request, response): # noqa
382394
self.add_proxito_headers(request, response)

readthedocs/proxito/tests/test_old_redirects.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1352,6 +1352,7 @@ def test_redirect_exact_with_wildcard_crossdomain(self):
13521352
r = self.client.get(url, headers={"host": "project.dev.readthedocs.io"})
13531353
self.assertEqual(r.status_code, 302, url)
13541354
self.assertEqual(r["Location"], expected_location, url)
1355+
self.assertNotIn("X-RTD-Resolver-Filename", r.headers)
13551356

13561357
def test_redirect_html_to_clean_url_crossdomain(self):
13571358
"""

0 commit comments

Comments
 (0)