Skip to content

Commit ae35351

Browse files
committed
Fixed is_safe_url() to reject URLs that use a scheme other than HTTP/S.
This is a security fix; disclosure to follow shortly.
1 parent 09a5f5a commit ae35351

File tree

2 files changed

+10
-5
lines changed

2 files changed

+10
-5
lines changed

Diff for: django/contrib/auth/tests/test_views.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,8 @@ def test_security_check(self, password='password'):
446446
for bad_url in ('http://example.com',
447447
'https://example.com',
448448
'ftp://exampel.com',
449-
'//example.com'):
449+
'//example.com',
450+
'javascript:alert("XSS")'):
450451

451452
nasty_url = '%(url)s?%(next)s=%(bad_url)s' % {
452453
'url': login_url,
@@ -467,6 +468,7 @@ def test_security_check(self, password='password'):
467468
'/view?param=ftp://exampel.com',
468469
'view/?param=//example.com',
469470
'https:///',
471+
'HTTPS:///',
470472
'//testserver/',
471473
'/url%20with%20spaces/'): # see ticket #12534
472474
safe_url = '%(url)s?%(next)s=%(good_url)s' % {
@@ -661,7 +663,8 @@ def test_security_check(self, password='password'):
661663
for bad_url in ('http://example.com',
662664
'https://example.com',
663665
'ftp://exampel.com',
664-
'//example.com'):
666+
'//example.com',
667+
'javascript:alert("XSS")'):
665668
nasty_url = '%(url)s?%(next)s=%(bad_url)s' % {
666669
'url': logout_url,
667670
'next': REDIRECT_FIELD_NAME,
@@ -680,6 +683,7 @@ def test_security_check(self, password='password'):
680683
'/view?param=ftp://exampel.com',
681684
'view/?param=//example.com',
682685
'https:///',
686+
'HTTPS:///',
683687
'//testserver/',
684688
'/url%20with%20spaces/'): # see ticket #12534
685689
safe_url = '%(url)s?%(next)s=%(good_url)s' % {

Diff for: django/utils/http.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -252,11 +252,12 @@ def same_origin(url1, url2):
252252
def is_safe_url(url, host=None):
253253
"""
254254
Return ``True`` if the url is a safe redirection (i.e. it doesn't point to
255-
a different host).
255+
a different host and uses a safe scheme).
256256
257257
Always returns ``False`` on an empty url.
258258
"""
259259
if not url:
260260
return False
261-
netloc = urllib_parse.urlparse(url)[1]
262-
return not netloc or netloc == host
261+
url_info = urllib_parse.urlparse(url)
262+
return (not url_info.netloc or url_info.netloc == host) and \
263+
(not url_info.scheme or url_info.scheme in ['http', 'https'])

0 commit comments

Comments
 (0)