Repository: wtforms/wtforms
Pull request #375 (2018-02-17 13:45:11)

Escape label unsafe chars
Added fix and tests for the issue #315.


Patch:
diff --git a/CHANGES.rst b/CHANGES.rst
index c1a8f3f..e651426 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -23,10 +23,14 @@ Unreleased
 -   The :class:`~widgets.TextArea` widget prepends a ``\r\n`` newline
     when rendering to account for browsers stripping an initial line for
     display. This does not affect the value. (`#238`_, `#395`_)
+-   :class:`~fields.core.Label` text is escaped before rendering.
+    (`#315`_, `#375`_)
 
 .. _#238: https://github.com/wtforms/wtforms/issues/238
 .. _#239: https://github.com/wtforms/wtforms/issues/239
+.. _#315: https://github.com/wtforms/wtforms/pull/315
 .. _#343: https://github.com/wtforms/wtforms/pull/343
+.. _#375: https://github.com/wtforms/wtforms/pull/375
 .. _#389: https://github.com/wtforms/wtforms/pull/389
 .. _#395: https://github.com/wtforms/wtforms/pull/395
 .. _#400: https://github.com/wtforms/wtforms/pull/400
diff --git a/wtforms/fields/core.py b/wtforms/fields/core.py
index b769757..e1bff72 100644
--- a/wtforms/fields/core.py
+++ b/wtforms/fields/core.py
@@ -1,19 +1,17 @@
 from __future__ import unicode_literals
 
+from copy import copy
 import datetime
 import decimal
 import itertools
 
-from copy import copy
-
-from markupsafe import Markup
+from markupsafe import Markup, escape
 
 from wtforms import widgets
-from wtforms.compat import text_type, izip
+from wtforms.compat import izip, text_type
 from wtforms.i18n import DummyTranslations
-from wtforms.validators import StopValidation
 from wtforms.utils import unset_value
-
+from wtforms.validators import StopValidation
 
 __all__ = (
     'BooleanField', 'DecimalField', 'DateField', 'DateTimeField', 'FieldList',
@@ -401,7 +399,8 @@ class Label(object):
             kwargs.setdefault('for', self.field_id)
 
         attributes = widgets.html_params(**kwargs)
-        return Markup('<label %s>%s</label>' % (attributes, text or self.text))
+        text = escape(text or self.text)
+        return Markup('<label %s>%s</label>' % (attributes, text))
 
     def __repr__(self):
         return 'Label(%r, %r)' % (self.field_id, self.text)
diff --git a/wtforms/widgets/core.py b/wtforms/widgets/core.py
index b099091..34a8704 100644
--- a/wtforms/widgets/core.py
+++ b/wtforms/widgets/core.py
@@ -1,6 +1,6 @@
 from __future__ import unicode_literals
 
-from markupsafe import escape, Markup
+from markupsafe import Markup, escape
 
 from wtforms.compat import iteritems, text_type
 


Test patch:
diff --git a/tests/test_fields.py b/tests/test_fields.py
index 575f081..6e105fe 100644
--- a/tests/test_fields.py
+++ b/tests/test_fields.py
@@ -74,6 +74,17 @@ class LabelTest(TestCase):
         self.assertEqual(label(for_='foo'), """<label for="foo">Caption</label>""")
         self.assertEqual(label(**{'for': 'bar'}), """<label for="bar">Caption</label>""")
 
+    def test_escaped_label_text(self):
+        label = Label('test', '<script>alert("test");</script>')
+        self.assertEqual(
+            label(for_='foo'),
+            """<label for="foo">&lt;script&gt;alert(&#34;test&#34;);&lt;/script&gt;</label>"""
+        )
+        self.assertEqual(
+            label(**{'for': 'bar'}),
+            """<label for="bar">&lt;script&gt;alert(&#34;test&#34;);&lt;/script&gt;</label>"""
+        )
+
 
 class FlagsTest(TestCase):
     def setUp(self):