VYPR
Moderate severityNVD Advisory· Published Jan 16, 2015· Updated May 6, 2026

CVE-2015-0220

CVE-2015-0220

Description

The django.util.http.is_safe_url function in Django before 1.4.18, 1.6.x before 1.6.10, and 1.7.x before 1.7.3 does not properly handle leading whitespaces, which allows remote attackers to conduct cross-site scripting (XSS) attacks via a crafted URL, related to redirect URLs, as demonstrated by a "\njavascript:" URL.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
DjangoPyPI
< 1.4.181.4.18
DjangoPyPI
>= 1.6, < 1.6.101.6.10
DjangoPyPI
>= 1.7, < 1.7.31.7.3

Affected products

18
  • cpe:2.3:o:canonical:ubuntu_linux:10.04:*:lts:*:*:*:*:*+ 3 more
    • cpe:2.3:o:canonical:ubuntu_linux:10.04:*:lts:*:*:*:*:*
    • cpe:2.3:o:canonical:ubuntu_linux:12.04:*:lts:*:*:*:*:*
    • cpe:2.3:o:canonical:ubuntu_linux:14.04:*:*:*:lts:*:*:*
    • cpe:2.3:o:canonical:ubuntu_linux:14.10:*:*:*:*:*:*:*
  • cpe:2.3:a:djangoproject:django:*:*:*:*:*:*:*:*+ 13 more
    • cpe:2.3:a:djangoproject:django:*:*:*:*:*:*:*:*range: <=1.4.17
    • cpe:2.3:a:djangoproject:django:1.6:*:*:*:*:*:*:*
    • cpe:2.3:a:djangoproject:django:1.6.1:*:*:*:*:*:*:*
    • cpe:2.3:a:djangoproject:django:1.6.2:*:*:*:*:*:*:*
    • cpe:2.3:a:djangoproject:django:1.6.3:*:*:*:*:*:*:*
    • cpe:2.3:a:djangoproject:django:1.6.4:*:*:*:*:*:*:*
    • cpe:2.3:a:djangoproject:django:1.6.5:*:*:*:*:*:*:*
    • cpe:2.3:a:djangoproject:django:1.6.6:*:*:*:*:*:*:*
    • cpe:2.3:a:djangoproject:django:1.6.7:*:*:*:*:*:*:*
    • cpe:2.3:a:djangoproject:django:1.6.8:*:*:*:*:*:*:*
    • cpe:2.3:a:djangoproject:django:1.6.9:*:*:*:*:*:*:*
    • cpe:2.3:a:djangoproject:django:1.7:*:*:*:*:*:*:*
    • cpe:2.3:a:djangoproject:django:1.7.1:*:*:*:*:*:*:*
    • cpe:2.3:a:djangoproject:django:1.7.2:*:*:*:*:*:*:*

Patches

3
4c241f1b710d

[1.4.x] Fixed is_safe_url() to handle leading whitespace.

https://github.com/django/djangoTim GrahamDec 3, 2014via ghsa
3 files changed · +19 3
  • django/utils/http.py+1 0 modified
    @@ -234,6 +234,7 @@ def is_safe_url(url, host=None):
         """
         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
    
  • docs/releases/1.4.18.txt+14 0 modified
    @@ -31,6 +31,20 @@ development server now does the same. Django's development server is not
     recommended for production use, but matching the behavior of common production
     servers reduces the surface area for behavior changes during deployment.
     
    +Mitigated possible XSS attack via user-supplied redirect URLs
    +=============================================================
    +
    +Django relies on user input in some cases (e.g.
    +:func:`django.contrib.auth.views.login` and :doc:`i18n </topics/i18n/index>`)
    +to redirect the user to an "on success" URL. The security checks for these
    +redirects (namely ``django.util.http.is_safe_url()``) didn't strip leading
    +whitespace on the tested URL and as such considered URLs like
    +``\njavascript:...`` safe. If a developer relied on ``is_safe_url()`` to
    +provide safe redirect targets and put such a URL into a link, they could suffer
    +from a XSS attack. This bug doesn't affect Django currently, since we only put
    +this URL into the ``Location`` response header and browsers seem to ignore
    +JavaScript there.
    +
     Bugfixes
     ========
     
    
  • tests/regressiontests/utils/http.py+4 3 modified
    @@ -64,7 +64,7 @@ def test_base36(self):
             # bad input
             for n in [-1, sys.maxint+1, '1', 'foo', {1:2}, (1,2,3)]:
                 self.assertRaises(ValueError, http.int_to_base36, n)
    -        
    +
             for n in ['#', ' ']:
                 self.assertRaises(ValueError, http.base36_to_int, n)
     
    @@ -73,7 +73,7 @@ def test_base36(self):
     
             # non-integer input
             self.assertRaises(TypeError, http.int_to_base36, 3.141)
    -        
    +
             # more explicit output testing
             for n, b36 in [(0, '0'), (1, '1'), (42, '16'), (818469960, 'django')]:
                 self.assertEqual(http.int_to_base36(n), b36)
    @@ -97,7 +97,8 @@ def test_is_safe_url(self):
                             'http:/\//example.com',
                             'http:\/example.com',
                             'http:/\example.com',
    -                        'javascript:alert("XSS")'):
    +                        'javascript:alert("XSS")'
    +                        '\njavascript:alert(x)'):
                 self.assertFalse(http.is_safe_url(bad_url, host='testserver'), "%s should be blocked" % bad_url)
             for good_url in ('/view/?param=http://example.com',
                          '/view/?param=https://example.com',
    
72e0b033662f

[1.6.x] Fixed is_safe_url() to handle leading whitespace.

https://github.com/django/djangoTim GrahamDec 3, 2014via ghsa
4 files changed · +31 1
  • django/utils/http.py+1 0 modified
    @@ -256,6 +256,7 @@ def is_safe_url(url, host=None):
         """
         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
    
  • docs/releases/1.4.18.txt+14 0 modified
    @@ -31,6 +31,20 @@ development server now does the same. Django's development server is not
     recommended for production use, but matching the behavior of common production
     servers reduces the surface area for behavior changes during deployment.
     
    +Mitigated possible XSS attack via user-supplied redirect URLs
    +=============================================================
    +
    +Django relies on user input in some cases (e.g.
    +:func:`django.contrib.auth.views.login` and :doc:`i18n </topics/i18n/index>`)
    +to redirect the user to an "on success" URL. The security checks for these
    +redirects (namely ``django.util.http.is_safe_url()``) didn't strip leading
    +whitespace on the tested URL and as such considered URLs like
    +``\njavascript:...`` safe. If a developer relied on ``is_safe_url()`` to
    +provide safe redirect targets and put such a URL into a link, they could suffer
    +from a XSS attack. This bug doesn't affect Django currently, since we only put
    +this URL into the ``Location`` response header and browsers seem to ignore
    +JavaScript there.
    +
     Bugfixes
     ========
     
    
  • docs/releases/1.6.10.txt+14 0 modified
    @@ -29,3 +29,17 @@ containing underscores from incoming requests by default. Django's built-in
     development server now does the same. Django's development server is not
     recommended for production use, but matching the behavior of common production
     servers reduces the surface area for behavior changes during deployment.
    +
    +Mitigated possible XSS attack via user-supplied redirect URLs
    +=============================================================
    +
    +Django relies on user input in some cases (e.g.
    +:func:`django.contrib.auth.views.login` and :doc:`i18n </topics/i18n/index>`)
    +to redirect the user to an "on success" URL. The security checks for these
    +redirects (namely ``django.util.http.is_safe_url()``) didn't strip leading
    +whitespace on the tested URL and as such considered URLs like
    +``\njavascript:...`` safe. If a developer relied on ``is_safe_url()`` to
    +provide safe redirect targets and put such a URL into a link, they could suffer
    +from a XSS attack. This bug doesn't affect Django currently, since we only put
    +this URL into the ``Location`` response header and browsers seem to ignore
    +JavaScript there.
    
  • tests/utils_tests/test_http.py+2 1 modified
    @@ -109,7 +109,8 @@ def test_is_safe_url(self):
                             'http:/\//example.com',
                             'http:\/example.com',
                             'http:/\example.com',
    -                        'javascript:alert("XSS")'):
    +                        'javascript:alert("XSS")',
    +                        '\njavascript:alert(x)'):
                 self.assertFalse(http.is_safe_url(bad_url, host='testserver'), "%s should be blocked" % bad_url)
             for good_url in ('/view/?param=http://example.com',
                          '/view/?param=https://example.com',
    
de67dedc771a

[1.7.x] Fixed is_safe_url() to handle leading whitespace.

https://github.com/django/djangoTim GrahamDec 3, 2014via ghsa
5 files changed · +45 1
  • django/utils/http.py+1 0 modified
    @@ -272,6 +272,7 @@ def is_safe_url(url, host=None):
         """
         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
    
  • docs/releases/1.4.18.txt+14 0 modified
    @@ -31,6 +31,20 @@ development server now does the same. Django's development server is not
     recommended for production use, but matching the behavior of common production
     servers reduces the surface area for behavior changes during deployment.
     
    +Mitigated possible XSS attack via user-supplied redirect URLs
    +=============================================================
    +
    +Django relies on user input in some cases (e.g.
    +:func:`django.contrib.auth.views.login` and :doc:`i18n </topics/i18n/index>`)
    +to redirect the user to an "on success" URL. The security checks for these
    +redirects (namely ``django.util.http.is_safe_url()``) didn't strip leading
    +whitespace on the tested URL and as such considered URLs like
    +``\njavascript:...`` safe. If a developer relied on ``is_safe_url()`` to
    +provide safe redirect targets and put such a URL into a link, they could suffer
    +from a XSS attack. This bug doesn't affect Django currently, since we only put
    +this URL into the ``Location`` response header and browsers seem to ignore
    +JavaScript there.
    +
     Bugfixes
     ========
     
    
  • docs/releases/1.6.10.txt+14 0 modified
    @@ -29,3 +29,17 @@ containing underscores from incoming requests by default. Django's built-in
     development server now does the same. Django's development server is not
     recommended for production use, but matching the behavior of common production
     servers reduces the surface area for behavior changes during deployment.
    +
    +Mitigated possible XSS attack via user-supplied redirect URLs
    +=============================================================
    +
    +Django relies on user input in some cases (e.g.
    +:func:`django.contrib.auth.views.login` and :doc:`i18n </topics/i18n/index>`)
    +to redirect the user to an "on success" URL. The security checks for these
    +redirects (namely ``django.util.http.is_safe_url()``) didn't strip leading
    +whitespace on the tested URL and as such considered URLs like
    +``\njavascript:...`` safe. If a developer relied on ``is_safe_url()`` to
    +provide safe redirect targets and put such a URL into a link, they could suffer
    +from a XSS attack. This bug doesn't affect Django currently, since we only put
    +this URL into the ``Location`` response header and browsers seem to ignore
    +JavaScript there.
    
  • docs/releases/1.7.3.txt+14 0 modified
    @@ -30,6 +30,20 @@ development server now does the same. Django's development server is not
     recommended for production use, but matching the behavior of common production
     servers reduces the surface area for behavior changes during deployment.
     
    +Mitigated possible XSS attack via user-supplied redirect URLs
    +=============================================================
    +
    +Django relies on user input in some cases (e.g.
    +:func:`django.contrib.auth.views.login` and :doc:`i18n </topics/i18n/index>`)
    +to redirect the user to an "on success" URL. The security checks for these
    +redirects (namely ``django.util.http.is_safe_url()``) didn't strip leading
    +whitespace on the tested URL and as such considered URLs like
    +``\njavascript:...`` safe. If a developer relied on ``is_safe_url()`` to
    +provide safe redirect targets and put such a URL into a link, they could suffer
    +from a XSS attack. This bug doesn't affect Django currently, since we only put
    +this URL into the ``Location`` response header and browsers seem to ignore
    +JavaScript there.
    +
     Bugfixes
     ========
     
    
  • tests/utils_tests/test_http.py+2 1 modified
    @@ -107,7 +107,8 @@ def test_is_safe_url(self):
                             'http:/\//example.com',
                             'http:\/example.com',
                             'http:/\example.com',
    -                        'javascript:alert("XSS")'):
    +                        'javascript:alert("XSS")',
    +                        '\njavascript:alert(x)'):
                 self.assertFalse(http.is_safe_url(bad_url, host='testserver'), "%s should be blocked" % bad_url)
             for good_url in ('/view/?param=http://example.com',
                          '/view/?param=https://example.com',
    

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

24

News mentions

0

No linked articles in our index yet.