diff --git a/django/contrib/markup/templatetags/markup.py b/django/contrib/markup/templatetags/markup.py
index a6b8dde655..b9fdce86a6 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
@@ -63,14 +65,25 @@ def markdown(value, arg=''):
safe_mode = True
else:
safe_mode = False
-
+ python_markdown_deprecation = "The use of Python-Markdown "
+ "< 2.1 in Django is deprecated; please update to the current version"
# 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):
+ warnings.warn(python_markdown_deprecation, DeprecationWarning)
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(python_markdown_deprecation, DeprecationWarning)
+ return mark_safe(markdown.markdown(force_unicode(value), extensions, safe_mode=safe_mode))
else:
+ warnings.warn(python_markdown_deprecation, DeprecationWarning)
return mark_safe(force_unicode(markdown.markdown(smart_str(value))))
@register.filter(is_safe=True)
diff --git a/django/contrib/markup/tests.py b/django/contrib/markup/tests.py
index 2eb64d5a9f..4539657bd4 100644
--- a/django/contrib/markup/tests.py
+++ b/django/contrib/markup/tests.py
@@ -58,6 +58,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("{% load markup %}{{ markdown_content|markdown }}")
diff --git a/docs/internals/deprecation.txt b/docs/internals/deprecation.txt
index cb91a1c0a3..81ca7afa27 100644
--- a/docs/internals/deprecation.txt
+++ b/docs/internals/deprecation.txt
@@ -196,6 +196,11 @@ these changes.
filesystem path to a ``locale`` directory containing non-app-specific
translations in its value.
+* The Markup contrib app will no longer support versions of Python-Markdown
+ library earlier than 2.1. An accelerated timeline was used as this was
+ a security related deprecation.
+
+
1.6
---
diff --git a/docs/ref/contrib/markup.txt b/docs/ref/contrib/markup.txt
index d671e46e2c..3abc27bf5d 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.
diff --git a/docs/releases/1.4.txt b/docs/releases/1.4.txt
index c3bbe480ea..d82ca03d28 100644
--- a/docs/releases/1.4.txt
+++ b/docs/releases/1.4.txt
@@ -1096,6 +1096,16 @@ field. This was something that should not have worked, and in 1.4 loading such
incomplete fixtures will fail. Because fixtures are a raw import, they should
explicitly specify all field values, regardless of field options on the model.
+Attributes disabled in markdown when safe mode set
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Prior to Django 1.4, attributes were included in any markdown output regardless
+of safe mode setting of the filter. With version > 2.1 of the Python-Markdown
+library, an enable_attributes option was added. When the safe argument is
+passed to the markdown filter, both the ``safe_mode=True`` and
+``enable_attributes=False`` options are set. If using a version of the
+Python-Markdown library less than 2.1, a warning is issued that the output is
+insecure.
Features deprecated in 1.4
==========================
@@ -1262,3 +1272,12 @@ each request to a site map now creates a new Paginator object and calls the
``items()`` method is doing, this may have a negative performance impact.
To mitigate the performance impact, consider using the :doc:`caching
framework ` within your ``Sitemap`` subclass.
+
+Versions of Python-Markdown earlier than 2.1
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Versions of Python-Markdown earlier than 2.1 do not support the option to
+disable attributes. As a security issue, earlier versions of this library will
+not be supported by the markup contrib app in 1.5 under an accelerated
+deprecation timeline.
+