diff --git a/django/utils/http.py b/django/utils/http.py index 6e782bd576..40a7d5f083 100644 --- a/django/utils/http.py +++ b/django/utils/http.py @@ -290,6 +290,8 @@ def is_safe_url(url, host=None): url = url.strip() if not url: return False + if six.PY2: + url = force_text(url, errors='replace') # Chrome treats \ completely as / in paths but it could be part of some # basic auth credentials so we need to check both URLs. return _is_safe_url(url, host) and _is_safe_url(url.replace('\\', '/'), host) diff --git a/docs/releases/1.8.11.txt b/docs/releases/1.8.11.txt index 9837371f7b..b01807129b 100644 --- a/docs/releases/1.8.11.txt +++ b/docs/releases/1.8.11.txt @@ -2,11 +2,7 @@ Django 1.8.11 release notes =========================== -*Under development* +*March 4, 2016* -Django 1.8.11 fixes several bugs in 1.8.10. - -Bugfixes -======== - -* ... +Django 1.8.11 fixes a regression on Python 2 in the 1.8.10 security release +where ``utils.http.is_safe_url()`` crashes on bytestring URLs (:ticket:`26308`). diff --git a/docs/releases/1.9.4.txt b/docs/releases/1.9.4.txt index 15adcee329..d3f66bb7a1 100644 --- a/docs/releases/1.9.4.txt +++ b/docs/releases/1.9.4.txt @@ -2,11 +2,7 @@ Django 1.9.4 release notes ========================== -*Under development* +*March 4, 2016* -Django 1.9.4 fixes several bugs in 1.9.3. - -Bugfixes -======== - -* ... +Django 1.9.4 fixes a regression on Python 2 in the 1.9.3 security release +where ``utils.http.is_safe_url()`` crashes on bytestring URLs (:ticket:`26308`). diff --git a/tests/utils_tests/test_http.py b/tests/utils_tests/test_http.py index 2a9b553b6a..3a1bbbf66e 100644 --- a/tests/utils_tests/test_http.py +++ b/tests/utils_tests/test_http.py @@ -1,3 +1,4 @@ +# -*- encoding: utf-8 -*- from __future__ import unicode_literals import sys @@ -114,6 +115,17 @@ class TestUtilsHttp(unittest.TestCase): 'http://testserver/confirm?email=me@example.com', '/url%20with%20spaces/'): self.assertTrue(http.is_safe_url(good_url, host='testserver'), "%s should be allowed" % good_url) + + if six.PY2: + # Check binary URLs, regression tests for #26308 + self.assertTrue( + http.is_safe_url(b'https://testserver/', host='testserver'), + "binary URLs should be allowed on Python 2" + ) + self.assertFalse(http.is_safe_url(b'\x08//example.com', host='testserver')) + self.assertTrue(http.is_safe_url('àview/'.encode('utf-8'), host='testserver')) + self.assertTrue(http.is_safe_url('àview'.encode('latin-1'), host='testserver')) + # Valid basic auth credentials are allowed. self.assertTrue(http.is_safe_url(r'http://user:pass@testserver/', host='user:pass@testserver')) # A path without host is allowed.