CVE-2014-0480
Description
The core.urlresolvers.reverse function in Django before 1.4.14, 1.5.x before 1.5.9, 1.6.x before 1.6.6, and 1.7 before release candidate 3 does not properly validate URLs, which allows remote attackers to conduct phishing attacks via a // (slash slash) in a URL, which triggers a scheme-relative URL to be generated.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
DjangoPyPI | < 1.4.14 | 1.4.14 |
DjangoPyPI | >= 1.5, < 1.5.9 | 1.5.9 |
DjangoPyPI | >= 1.6, < 1.6.6 | 1.6.6 |
Affected products
42cpe:2.3:a:djangoproject:django:*:*:*:*:*:*:*:*+ 39 more
- cpe:2.3:a:djangoproject:django:*:*:*:*:*:*:*:*range: <=1.4.13
- 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.10:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.4.11:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.4.12:*:*:*:*:*:*:*
- 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.4.6:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.4.7:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.4.8:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.4.9:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.5:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.5.1:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.5.2:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.5.3:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.5.4:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.5.5:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.5.6:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.5.7:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.5.8:*:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.5:alpha:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.5:beta:*:*:*:*:*:*
- 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:beta1:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.6:beta2:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.6:beta3:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.6:beta4:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.7:beta1:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.7:beta2:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.7:beta3:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.7:beta4:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.7:rc1:*:*:*:*:*:*
- cpe:2.3:a:djangoproject:django:1.7:rc2:*:*:*:*:*:*
Patches
3da051da8df5e[1.6.x] Prevented reverse() from generating URLs pointing to other hosts.
6 files changed · +50 −1
django/core/urlresolvers.py+5 −1 modified@@ -435,7 +435,11 @@ def _reverse_with_prefix(self, lookup_view, _prefix, *args, **kwargs): candidate_pat = prefix_norm.replace('%', '%%') + result if re.search('^%s%s' % (prefix_norm, pattern), candidate_pat % candidate_subs, re.UNICODE): candidate_subs = dict((k, urlquote(v)) for (k, v) in candidate_subs.items()) - return candidate_pat % candidate_subs + url = candidate_pat % candidate_subs + # Don't allow construction of scheme relative urls. + if url.startswith('//'): + url = '/%%2F%s' % url[2:] + return url # lookup_view can be URL label, or dotted path, or callable, Any of # these can be passed in at the top, but callables are not friendly in # error messages.
docs/releases/1.4.14.txt+13 −0 modified@@ -5,3 +5,16 @@ Django 1.4.14 release notes *Under development* Django 1.4.14 fixes several security issues in 1.4.13. + +:func:`~django.core.urlresolvers.reverse()` could generate URLs pointing to other hosts +======================================================================================= + +In certain situations, URL reversing could generate scheme-relative URLs (URLs +starting with two slashes), which could unexpectedly redirect a user to a +different host. An attacker could exploit this, for example, by redirecting +users to a phishing site designed to ask for user's passwords. + +To remedy this, URL reversing now ensures that no URL starts with two slashes +(//), replacing the second slash with its URL encoded counterpart (%2F). This +approach ensures that semantics stay the same, while making the URL relative to +the domain and not to the scheme.
docs/releases/1.5.9.txt+13 −0 modified@@ -5,3 +5,16 @@ Django 1.5.9 release notes *Under development* Django 1.5.9 fixes several security issues in 1.5.8. + +:func:`~django.core.urlresolvers.reverse()` could generate URLs pointing to other hosts +======================================================================================= + +In certain situations, URL reversing could generate scheme-relative URLs (URLs +starting with two slashes), which could unexpectedly redirect a user to a +different host. An attacker could exploit this, for example, by redirecting +users to a phishing site designed to ask for user's passwords. + +To remedy this, URL reversing now ensures that no URL starts with two slashes +(//), replacing the second slash with its URL encoded counterpart (%2F). This +approach ensures that semantics stay the same, while making the URL relative to +the domain and not to the scheme.
docs/releases/1.6.6.txt+13 −0 modified@@ -6,6 +6,19 @@ Django 1.6.6 release notes Django 1.6.6 fixes several security issues and bugs in 1.6.5. +:func:`~django.core.urlresolvers.reverse()` could generate URLs pointing to other hosts +======================================================================================= + +In certain situations, URL reversing could generate scheme-relative URLs (URLs +starting with two slashes), which could unexpectedly redirect a user to a +different host. An attacker could exploit this, for example, by redirecting +users to a phishing site designed to ask for user's passwords. + +To remedy this, URL reversing now ensures that no URL starts with two slashes +(//), replacing the second slash with its URL encoded counterpart (%2F). This +approach ensures that semantics stay the same, while making the URL relative to +the domain and not to the scheme. + Bugfixes ========
tests/urlpatterns_reverse/tests.py+3 −0 modified@@ -147,6 +147,9 @@ ('defaults', '/defaults_view2/3/', [], {'arg1': 3, 'arg2': 2}), ('defaults', NoReverseMatch, [], {'arg1': 3, 'arg2': 3}), ('defaults', NoReverseMatch, [], {'arg2': 1}), + + # Security tests + ('security', '/%2Fexample.com/security/', ['/example.com'], {}), ) class NoURLPatternsTests(TestCase):
tests/urlpatterns_reverse/urls.py+3 −0 modified@@ -71,4 +71,7 @@ (r'defaults_view2/(?P<arg1>\d+)/', 'defaults_view', {'arg2': 2}, 'defaults'), url('^includes/', include(other_patterns)), + + # Security tests + url('(.+)/security/$', empty_view, name='security'), )
c2fe73133b62[1.4.x] Prevented reverse() from generating URLs pointing to other hosts.
4 files changed · +21 −0
django/core/urlresolvers.py+2 −0 modified@@ -406,6 +406,8 @@ def _reverse_with_prefix(self, lookup_view, _prefix, *args, **kwargs): unicode_kwargs = dict([(k, force_unicode(v)) for (k, v) in kwargs.items()]) candidate = (prefix_norm + result) % unicode_kwargs if re.search(u'^%s%s' % (_prefix, pattern), candidate, re.UNICODE): + if candidate.startswith('//'): + candidate = '/%%2F%s' % candidate[2:] return candidate # lookup_view can be URL label, or dotted path, or callable, Any of # these can be passed in at the top, but callables are not friendly in
docs/releases/1.4.14.txt+13 −0 modified@@ -5,3 +5,16 @@ Django 1.4.14 release notes *Under development* Django 1.4.14 fixes several security issues in 1.4.13. + +:func:`~django.core.urlresolvers.reverse()` could generate URLs pointing to other hosts +======================================================================================= + +In certain situations, URL reversing could generate scheme-relative URLs (URLs +starting with two slashes), which could unexpectedly redirect a user to a +different host. An attacker could exploit this, for example, by redirecting +users to a phishing site designed to ask for user's passwords. + +To remedy this, URL reversing now ensures that no URL starts with two slashes +(//), replacing the second slash with its URL encoded counterpart (%2F). This +approach ensures that semantics stay the same, while making the URL relative to +the domain and not to the scheme.
tests/regressiontests/urlpatterns_reverse/tests.py+3 −0 modified@@ -142,6 +142,9 @@ ('defaults', '/defaults_view2/3/', [], {'arg1': 3, 'arg2': 2}), ('defaults', NoReverseMatch, [], {'arg1': 3, 'arg2': 3}), ('defaults', NoReverseMatch, [], {'arg2': 1}), + + # Security tests + ('security', '/%2Fexample.com/security/', ['/example.com'], {}), ) class NoURLPatternsTests(TestCase):
tests/regressiontests/urlpatterns_reverse/urls.py+3 −0 modified@@ -71,4 +71,7 @@ (r'defaults_view2/(?P<arg1>\d+)/', 'defaults_view', {'arg2': 2}, 'defaults'), url('^includes/', include(other_patterns)), + + # Security tests + url('(.+)/security/$', empty_view, name='security'), )
45ac9d4fb087[1.5.x] Prevented reverse() from generating URLs pointing to other hosts.
5 files changed · +34 −0
django/core/urlresolvers.py+2 −0 modified@@ -426,6 +426,8 @@ def _reverse_with_prefix(self, lookup_view, _prefix, *args, **kwargs): unicode_kwargs = dict([(k, force_text(v)) for (k, v) in kwargs.items()]) candidate = (prefix_norm.replace('%', '%%') + result) % unicode_kwargs if re.search('^%s%s' % (prefix_norm, pattern), candidate, re.UNICODE): + if candidate.startswith('//'): + candidate = '/%%2F%s' % candidate[2:] return candidate # lookup_view can be URL label, or dotted path, or callable, Any of # these can be passed in at the top, but callables are not friendly in
docs/releases/1.4.14.txt+13 −0 modified@@ -5,3 +5,16 @@ Django 1.4.14 release notes *Under development* Django 1.4.14 fixes several security issues in 1.4.13. + +:func:`~django.core.urlresolvers.reverse()` could generate URLs pointing to other hosts +======================================================================================= + +In certain situations, URL reversing could generate scheme-relative URLs (URLs +starting with two slashes), which could unexpectedly redirect a user to a +different host. An attacker could exploit this, for example, by redirecting +users to a phishing site designed to ask for user's passwords. + +To remedy this, URL reversing now ensures that no URL starts with two slashes +(//), replacing the second slash with its URL encoded counterpart (%2F). This +approach ensures that semantics stay the same, while making the URL relative to +the domain and not to the scheme.
docs/releases/1.5.9.txt+13 −0 modified@@ -5,3 +5,16 @@ Django 1.5.9 release notes *Under development* Django 1.5.9 fixes several security issues in 1.5.8. + +:func:`~django.core.urlresolvers.reverse()` could generate URLs pointing to other hosts +======================================================================================= + +In certain situations, URL reversing could generate scheme-relative URLs (URLs +starting with two slashes), which could unexpectedly redirect a user to a +different host. An attacker could exploit this, for example, by redirecting +users to a phishing site designed to ask for user's passwords. + +To remedy this, URL reversing now ensures that no URL starts with two slashes +(//), replacing the second slash with its URL encoded counterpart (%2F). This +approach ensures that semantics stay the same, while making the URL relative to +the domain and not to the scheme.
tests/regressiontests/urlpatterns_reverse/tests.py+3 −0 modified@@ -143,6 +143,9 @@ ('defaults', '/defaults_view2/3/', [], {'arg1': 3, 'arg2': 2}), ('defaults', NoReverseMatch, [], {'arg1': 3, 'arg2': 3}), ('defaults', NoReverseMatch, [], {'arg2': 1}), + + # Security tests + ('security', '/%2Fexample.com/security/', ['/example.com'], {}), ) class NoURLPatternsTests(TestCase):
tests/regressiontests/urlpatterns_reverse/urls.py+3 −0 modified@@ -71,4 +71,7 @@ (r'defaults_view2/(?P<arg1>\d+)/', 'defaults_view', {'arg2': 2}, 'defaults'), url('^includes/', include(other_patterns)), + + # Security tests + url('(.+)/security/$', empty_view, name='security'), )
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
15- www.djangoproject.com/weblog/2014/aug/20/security/nvdPatchVendor Advisory
- github.com/advisories/GHSA-f7cm-ccfp-3q4rghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2014-0480ghsaADVISORY
- lists.opensuse.org/opensuse-updates/2014-09/msg00023.htmlnvdWEB
- www.debian.org/security/2014/dsa-3010nvdWEB
- github.com/django/django/commit/45ac9d4fb087d21902469fc22643f5201d41a0cdghsaWEB
- github.com/django/django/commit/c2fe73133b62a1d9e8f7a6b43966570b14618d7eghsaWEB
- github.com/django/django/commit/da051da8df5e69944745072611351d4cfc6435d5ghsaWEB
- github.com/pypa/advisory-database/tree/main/vulns/django/PYSEC-2014-4.yamlghsaWEB
- web.archive.org/web/20140918034351/http://www.securityfocus.com/bid/69425ghsaWEB
- www.djangoproject.com/weblog/2014/aug/20/securityghsaWEB
- secunia.com/advisories/59782nvd
- secunia.com/advisories/61276nvd
- secunia.com/advisories/61281nvd
- www.securityfocus.com/bid/69425nvd
News mentions
0No linked articles in our index yet.