diff options
| author | Tim Graham <timograham@gmail.com> | 2015-03-09 20:05:13 -0400 |
|---|---|---|
| committer | Tim Graham <timograham@gmail.com> | 2015-03-18 08:39:37 -0400 |
| commit | 2342693b31f740a422abf7267c53b4e7bc487c1b (patch) | |
| tree | 671ee7ae37806f22e653000b34ffb068b6824a1a /django | |
| parent | 3b20558beb6abef0b53f3c8e4ca6b598219f1d0d (diff) | |
[1.4.x] Made is_safe_url() reject URLs that start with control characters.
This is a security fix; disclosure to follow shortly.
Diffstat (limited to 'django')
| -rw-r--r-- | django/utils/http.py | 9 |
1 files changed, 8 insertions, 1 deletions
diff --git a/django/utils/http.py b/django/utils/http.py index e69a92b578..b8c81a8418 100644 --- a/django/utils/http.py +++ b/django/utils/http.py @@ -4,6 +4,7 @@ import re import sys import urllib import urlparse +import unicodedata from email.utils import formatdate from django.utils.datastructures import MultiValueDict @@ -232,9 +233,10 @@ def is_safe_url(url, host=None): Always returns ``False`` on an empty url. """ + if url is not None: + url = url.strip() if not url: return False - url = url.strip() # Chrome treats \ completely as / url = url.replace('\\', '/') # Chrome considers any URL with more than two slashes to be absolute, but @@ -248,5 +250,10 @@ def is_safe_url(url, host=None): # allow this syntax. if not url_info[1] and url_info[0]: return False + # Forbid URLs that start with control characters. Some browsers (like + # Chrome) ignore quite a few control characters at the start of a + # URL and might consider the URL as scheme relative. + if unicodedata.category(unicode(url[0]))[0] == 'C': + return False return (not url_info[1] or url_info[1] == host) and \ (not url_info[0] or url_info[0] in ['http', 'https']) |
