CVE-2013-6044
Description
The is_safe_url function in utils/http.py in Django 1.4.x before 1.4.6, 1.5.x before 1.5.2, and 1.6 before beta 2 treats a URL's scheme as safe even if it is not HTTP or HTTPS, which might introduce cross-site scripting (XSS) or other vulnerabilities into Django applications that use this function, as demonstrated by "the login view in django.contrib.auth.views" and the javascript: scheme.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
DjangoPyPI | >= 1.4, < 1.4.6 | 1.4.6 |
DjangoPyPI | >= 1.5, < 1.5.2 | 1.5.2 |
Affected products
8cpe:2.3:a:djangoproject:django:1.4:*:*:*:*:*:*:*+ 7 more
- cpe:2.3:a:djangoproject:django:1.4:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.4.1:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.4.2:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.4.4:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.4.5:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.5:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.5.1:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.6:beta1:*:*:*:*:*:*
Patches
3ae3535169af8Fixed is_safe_url() to reject URLs that use a scheme other than HTTP/S.
2 files changed · +10 −5
django/contrib/auth/tests/test_views.py+6 −2 modified@@ -446,7 +446,8 @@ def test_security_check(self, password='password'): for bad_url in ('http://example.com', 'https://example.com', 'ftp://exampel.com', - '//example.com'): + '//example.com', + 'javascript:alert("XSS")'): nasty_url = '%(url)s?%(next)s=%(bad_url)s' % { 'url': login_url, @@ -467,6 +468,7 @@ def test_security_check(self, password='password'): '/view?param=ftp://exampel.com', 'view/?param=//example.com', 'https:///', + 'HTTPS:///', '//testserver/', '/url%20with%20spaces/'): # see ticket #12534 safe_url = '%(url)s?%(next)s=%(good_url)s' % { @@ -661,7 +663,8 @@ def test_security_check(self, password='password'): for bad_url in ('http://example.com', 'https://example.com', 'ftp://exampel.com', - '//example.com'): + '//example.com', + 'javascript:alert("XSS")'): nasty_url = '%(url)s?%(next)s=%(bad_url)s' % { 'url': logout_url, 'next': REDIRECT_FIELD_NAME, @@ -680,6 +683,7 @@ def test_security_check(self, password='password'): '/view?param=ftp://exampel.com', 'view/?param=//example.com', 'https:///', + 'HTTPS:///', '//testserver/', '/url%20with%20spaces/'): # see ticket #12534 safe_url = '%(url)s?%(next)s=%(good_url)s' % {
django/utils/http.py+4 −3 modified@@ -252,11 +252,12 @@ def same_origin(url1, url2): def is_safe_url(url, host=None): """ Return ``True`` if the url is a safe redirection (i.e. it doesn't point to - a different host). + a different host and uses a safe scheme). Always returns ``False`` on an empty url. """ if not url: return False - netloc = urllib_parse.urlparse(url)[1] - return not netloc or netloc == host + url_info = urllib_parse.urlparse(url) + return (not url_info.netloc or url_info.netloc == host) and \ + (not url_info.scheme or url_info.scheme in ['http', 'https'])
1a274ccd6bc1Fixed is_safe_url() to reject URLs that use a scheme other than HTTP/S.
2 files changed · +10 −5
django/contrib/auth/tests/views.py+6 −2 modified@@ -328,7 +328,8 @@ def test_security_check(self, password='password'): for bad_url in ('http://example.com', 'https://example.com', 'ftp://exampel.com', - '//example.com'): + '//example.com', + 'javascript:alert("XSS")'): nasty_url = '%(url)s?%(next)s=%(bad_url)s' % { 'url': login_url, @@ -349,6 +350,7 @@ def test_security_check(self, password='password'): '/view?param=ftp://exampel.com', 'view/?param=//example.com', 'https:///', + 'HTTPS:///', '//testserver/', '/url%20with%20spaces/'): # see ticket #12534 safe_url = '%(url)s?%(next)s=%(good_url)s' % { @@ -522,7 +524,8 @@ def test_security_check(self, password='password'): for bad_url in ('http://example.com', 'https://example.com', 'ftp://exampel.com', - '//example.com'): + '//example.com', + 'javascript:alert("XSS")'): nasty_url = '%(url)s?%(next)s=%(bad_url)s' % { 'url': logout_url, 'next': REDIRECT_FIELD_NAME, @@ -541,6 +544,7 @@ def test_security_check(self, password='password'): '/view?param=ftp://exampel.com', 'view/?param=//example.com', 'https:///', + 'HTTPS:///', '//testserver/', '/url%20with%20spaces/'): # see ticket #12534 safe_url = '%(url)s?%(next)s=%(good_url)s' % {
django/utils/http.py+4 −3 modified@@ -231,11 +231,12 @@ def same_origin(url1, url2): def is_safe_url(url, host=None): """ Return ``True`` if the url is a safe redirection (i.e. it doesn't point to - a different host). + a different host and uses a safe scheme). Always returns ``False`` on an empty url. """ if not url: return False - netloc = urllib_parse.urlparse(url)[1] - return not netloc or netloc == host + url_info = urllib_parse.urlparse(url) + return (not url_info.netloc or url_info.netloc == host) and \ + (not url_info.scheme or url_info.scheme in ['http', 'https'])
ec67af0bd609Fixed is_safe_url() to reject URLs that use a scheme other than HTTP/S.
2 files changed · +10 −5
django/contrib/auth/tests/views.py+6 −2 modified@@ -309,7 +309,8 @@ def test_security_check(self, password='password'): for bad_url in ('http://example.com', 'https://example.com', 'ftp://exampel.com', - '//example.com'): + '//example.com', + 'javascript:alert("XSS")'): nasty_url = '%(url)s?%(next)s=%(bad_url)s' % { 'url': login_url, @@ -330,6 +331,7 @@ def test_security_check(self, password='password'): '/view?param=ftp://exampel.com', 'view/?param=//example.com', 'https:///', + 'HTTPS:///', '//testserver/', '/url%20with%20spaces/'): # see ticket #12534 safe_url = '%(url)s?%(next)s=%(good_url)s' % { @@ -467,7 +469,8 @@ def test_security_check(self, password='password'): for bad_url in ('http://example.com', 'https://example.com', 'ftp://exampel.com', - '//example.com'): + '//example.com', + 'javascript:alert("XSS")'): nasty_url = '%(url)s?%(next)s=%(bad_url)s' % { 'url': logout_url, 'next': REDIRECT_FIELD_NAME, @@ -486,6 +489,7 @@ def test_security_check(self, password='password'): '/view?param=ftp://exampel.com', 'view/?param=//example.com', 'https:///', + 'HTTPS:///', '//testserver/', '/url%20with%20spaces/'): # see ticket #12534 safe_url = '%(url)s?%(next)s=%(good_url)s' % {
django/utils/http.py+4 −3 modified@@ -228,11 +228,12 @@ def same_origin(url1, url2): def is_safe_url(url, host=None): """ Return ``True`` if the url is a safe redirection (i.e. it doesn't point to - a different host). + a different host and uses a safe scheme). Always returns ``False`` on an empty url. """ if not url: return False - netloc = urlparse.urlparse(url)[1] - return not netloc or netloc == host + url_info = urlparse.urlparse(url) + return (not url_info[1] or url_info[1] == host) and \ + (not url_info[0] or url_info[0] in ['http', 'https'])
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
16- www.djangoproject.com/weblog/2013/aug/13/security-releases-issuednvdPatchVendor AdvisoryWEB
- secunia.com/advisories/54476nvdVendor Advisory
- github.com/advisories/GHSA-9cwg-mhxf-hh59ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2013-6044ghsaADVISORY
- lists.opensuse.org/opensuse-updates/2013-10/msg00015.htmlnvdWEB
- rhn.redhat.com/errata/RHSA-2013-1521.htmlnvdWEB
- seclists.org/oss-sec/2013/q3/369nvdWEB
- seclists.org/oss-sec/2013/q3/411nvdWEB
- www.debian.org/security/2013/dsa-2740nvdWEB
- exchange.xforce.ibmcloud.com/vulnerabilities/86437nvdWEB
- github.com/django/django/commit/1a274ccd6bc1afbdac80344c9b6e5810c1162b5fnvdWEB
- github.com/django/django/commit/ae3535169af804352517b7fea94a42a1c9c4b762nvdWEB
- github.com/django/django/commit/ec67af0bd609c412b76eaa4cc89968a2a8e5ad6anvdWEB
- github.com/pypa/advisory-database/tree/main/vulns/django/PYSEC-2013-21.yamlghsaWEB
- www.securityfocus.com/bid/61777nvd
- www.securitytracker.com/id/1028915nvd
News mentions
0No linked articles in our index yet.