From 1f924cf72d76466a359371267c448d19c4e1352a Mon Sep 17 00:00:00 2001 From: Paul McMillan Date: Wed, 14 Mar 2012 18:51:20 +0000 Subject: [PATCH] [1.3.X] Fixed #17837. Improved markdown safety. Markdown enable_attributes is now False when safe_mode is enabled. Documented the markdown "safe" argument. Added warnings when the safe argument is passed to versions of markdown which cannot be made safe. git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.3.X@17734 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/contrib/markup/templatetags/markup.py | 17 +++++++++++++++-- django/contrib/markup/tests.py | 14 ++++++++++++++ docs/ref/contrib/markup.txt | 16 ++++++++++++++++ 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/django/contrib/markup/templatetags/markup.py b/django/contrib/markup/templatetags/markup.py index 7cdc04c653..66cb12b008 100644 --- a/django/contrib/markup/templatetags/markup.py +++ b/django/contrib/markup/templatetags/markup.py @@ -11,6 +11,8 @@ markup syntaxes to HTML; currently there is support for: * reStructuredText, which requires docutils from http://docutils.sf.net/ """ +import warnings + from django import template from django.conf import settings from django.utils.encoding import smart_str, force_unicode @@ -65,10 +67,21 @@ def markdown(value, arg=''): # Unicode support only in markdown v1.7 or above. Version_info # exist only in markdown v1.6.2rc-2 or above. - if getattr(markdown, "version_info", None) < (1,7): + markdown_vers = getattr(markdown, "version_info", None) + if markdown_vers < (1,7): return mark_safe(force_unicode(markdown.markdown(smart_str(value), extensions, safe_mode=safe_mode))) else: - return mark_safe(markdown.markdown(force_unicode(value), extensions, safe_mode=safe_mode)) + if markdown_vers >= (2,1): + if safe_mode: + return mark_safe(markdown.markdown(force_unicode(value), extensions, safe_mode=safe_mode, enable_attributes=False)) + else: + return mark_safe(markdown.markdown(force_unicode(value), extensions, safe_mode=safe_mode)) + else: + warnings.warn("Versions of markdown prior to 2.1 do not " + "support disabling of attributes, no " + "attributes have been removed and the result " + "is insecure.") + return mark_safe(markdown.markdown(force_unicode(value), extensions, safe_mode=safe_mode)) else: return mark_safe(force_unicode(markdown.markdown(smart_str(value)))) markdown.is_safe = True diff --git a/django/contrib/markup/tests.py b/django/contrib/markup/tests.py index e97a7def3b..6903dd7d85 100644 --- a/django/contrib/markup/tests.py +++ b/django/contrib/markup/tests.py @@ -60,6 +60,20 @@ Paragraph 2 with a link_ pattern = re.compile("""

Paragraph 1\s*

\s*

\s*An h2

""") self.assertTrue(pattern.match(rendered)) + @unittest.skipUnless(markdown, 'markdown no installed') + def test_markdown_attribute_disable(self): + t = Template("{% load markup %}{{ markdown_content|markdown:'safe' }}") + markdown_content = "{@onclick=alert('hi')}some paragraph" + rendered = t.render(Context({'markdown_content':markdown_content})).strip() + self.assertTrue('@' in rendered) + + @unittest.skipUnless(markdown, 'markdown no installed') + def test_markdown_attribute_enable(self): + t = Template("{% load markup %}{{ markdown_content|markdown }}") + markdown_content = "{@onclick=alert('hi')}some paragraph" + rendered = t.render(Context({'markdown_content':markdown_content})).strip() + self.assertFalse('@' in rendered) + @unittest.skipIf(markdown, 'markdown is installed') def test_no_markdown(self): t = Template("{{ markdown_content|markdown }}") diff --git a/docs/ref/contrib/markup.txt b/docs/ref/contrib/markup.txt index 7f43810674..09cb080221 100644 --- a/docs/ref/contrib/markup.txt +++ b/docs/ref/contrib/markup.txt @@ -47,3 +47,19 @@ override the default writer settings. See the `restructuredtext writer settings`_ for details on what these settings are. .. _restructuredtext writer settings: http://docutils.sourceforge.net/docs/user/config.html#html4css1-writer + +Markdown +-------- + +The Python Markdown library supports options named "safe_mode" and +"enable_attributes". Both relate to the security of the output. To enable both +options in tandem, the markdown filter supports the "safe" argument. + + {{ markdown_content_var|markdown:"safe" }} + +.. warning:: + + Versions of the Python-Markdown library prior to 2.1 do not support the + optional disabling of attributes and by default they will be included in + any output from the markdown filter - a warning is issued if this is the + case.