Skip to content
Permalink
Browse files Browse the repository at this point in the history
Fix a XSS vulnerability in the gravatar template tag.
The generated gravatar HTML wasn't handling escaping of the display name
of the user, allowing an attacker to choose a name that would close out
the <img> tag and inject a <script> tag.

By switching to Django's format_html(), we can guarantee safe escaping
of content.
  • Loading branch information
chipx86 committed Jun 6, 2014
1 parent 77a68c0 commit 77ac646
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 3 deletions.
8 changes: 5 additions & 3 deletions djblets/gravatars/templatetags/gravatars.py
Expand Up @@ -25,6 +25,7 @@
from __future__ import unicode_literals

from django import template
from django.utils.html import format_html

from djblets.gravatars import (get_gravatar_url,
get_gravatar_url_for_email)
Expand Down Expand Up @@ -55,9 +56,10 @@ def gravatar(context, user, size=None):
url = get_gravatar_url(context['request'], user, size)

if url:
return ('<img src="%s" width="%s" height="%s" alt="%s" '
' class="gravatar"/>' %
(url, size, size, user.get_full_name() or user.username))
return format_html(
'<img src="{0}" width="{1}" height="{1}" alt="{2}" '
'class="gravatar"/>',
url, size, user.get_full_name() or user.username)
else:
return ''

Expand Down
34 changes: 34 additions & 0 deletions djblets/gravatars/templatetags/tests.py
@@ -0,0 +1,34 @@
from __future__ import unicode_literals

from django.contrib.auth.models import User
from django.template import Token, TOKEN_TEXT

from djblets.testing.testcases import TagTest
from djblets.gravatars.templatetags.gravatars import gravatar


class DummyRequest(object):
def is_secure(self):
return False


class TagTests(TagTest):
"""Unit tests for gravatars template tags."""
def test_gravatar_xss(self):
"""Testing {% gravatar %} doesn't allow XSS injection"""
user = User(username='test',
first_name='"><script>alert(1);</script><"',
email='test@example.com')

node = gravatar(self.parser, Token(TOKEN_TEXT, 'gravatar user 32'))
context = {
'request': DummyRequest(),
'user': user,
}

self.assertEqual(
node.render(context),
'<img src="http://www.gravatar.com/avatar/'
'55502f40dc8b7c769880b10874abc9d0?s=32" width="32" height="32" '
'alt="&quot;&gt;&lt;script&gt;alert(1);&lt;/script&gt;&lt;&quot;" '
'class="gravatar"/>')

0 comments on commit 77ac646

Please sign in to comment.