Corrected HTML-escaping behaviour of url template tag.

Due to the URL encoding applied by the tag for all parameters that might be
partly controllable by an end-user, there are no XSS/security problems
caused by this bug, only invalid HTML.
This commit is contained in:
Luke Plant 2015-07-21 13:35:11 +01:00
parent 927b30a6ab
commit 8a5eadd140
2 changed files with 13 additions and 2 deletions

View File

@ -12,7 +12,7 @@ from django.conf import settings
from django.utils import six, timezone from django.utils import six, timezone
from django.utils.deprecation import RemovedInDjango110Warning from django.utils.deprecation import RemovedInDjango110Warning
from django.utils.encoding import force_text, smart_text from django.utils.encoding import force_text, smart_text
from django.utils.html import format_html from django.utils.html import conditional_escape, format_html
from django.utils.lorem_ipsum import paragraphs, words from django.utils.lorem_ipsum import paragraphs, words
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
@ -512,6 +512,8 @@ class URLNode(Node):
context[self.asvar] = url context[self.asvar] = url
return '' return ''
else: else:
if context.autoescape:
url = conditional_escape(url)
return url return url

View File

@ -95,7 +95,7 @@ class UrlTagTests(SimpleTestCase):
@ignore_warnings(category=RemovedInDjango110Warning) @ignore_warnings(category=RemovedInDjango110Warning)
def test_url12(self): def test_url12(self):
output = self.engine.render_to_string('url12', {'client': {'id': 1}}) output = self.engine.render_to_string('url12', {'client': {'id': 1}})
self.assertEqual(output, '/client/1/!$&\'()*+,;=~:@,/') self.assertEqual(output, '/client/1/!$&'()*+,;=~:@,/')
@ignore_warnings(category=RemovedInDjango110Warning) @ignore_warnings(category=RemovedInDjango110Warning)
@setup({'url13': '{% url "template_tests.views.client_action" ' @setup({'url13': '{% url "template_tests.views.client_action" '
@ -133,6 +133,15 @@ class UrlTagTests(SimpleTestCase):
output = self.engine.render_to_string('url20', {'client': {'id': 1}, 'url_name_in_var': 'named.client'}) output = self.engine.render_to_string('url20', {'client': {'id': 1}, 'url_name_in_var': 'named.client'})
self.assertEqual(output, '/named-client/1/') self.assertEqual(output, '/named-client/1/')
@setup({'url21': '{% autoescape off %}'
'{% url "template_tests.views.client_action" '
'id=client.id action="!$&\'()*+,;=~:@," %}'
'{% endautoescape %}'})
@ignore_warnings(category=RemovedInDjango110Warning)
def test_url21(self):
output = self.engine.render_to_string('url21', {'client': {'id': 1}})
self.assertEqual(output, '/client/1/!$&\'()*+,;=~:@,/')
# Failures # Failures
@setup({'url-fail01': '{% url %}'}) @setup({'url-fail01': '{% url %}'})
def test_url_fail01(self): def test_url_fail01(self):