diff --git a/requirements.txt b/requirements.txt index 05b21086..9769ddb3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -25,6 +25,7 @@ celery==3.1.12 redis==2.10.3 Unidecode==0.04.16 raven==5.1.1 +bleach==1.4 # Comment it if you are using python >= 3.4 enum34==1.0 diff --git a/taiga/mdrender/service.py b/taiga/mdrender/service.py index baeb6c3d..f9dc0ee5 100644 --- a/taiga/mdrender/service.py +++ b/taiga/mdrender/service.py @@ -16,6 +16,23 @@ import hashlib import functools +import bleach + +# BEGIN PATCH +import html5lib +from html5lib.serializer.htmlserializer import HTMLSerializer + +def _serialize(domtree): + walker = html5lib.treewalkers.getTreeWalker('etree') + stream = walker(domtree) + serializer = HTMLSerializer(quote_attr_values=True, + omit_optional_tags=False, + alphabetical_attributes=True) + + return serializer.render(stream) + +bleach._serialize = _serialize +### END PATCH from django.core.cache import cache from django.utils.encoding import force_bytes @@ -34,6 +51,15 @@ from .extensions.mentions import MentionsExtension from .extensions.references import TaigaReferencesExtension +ALLOWED_TAGS = bleach.ALLOWED_TAGS + ["p", "table", "th", "tr", "td", "h1", + "h2", "h3", "div", "pre", "span", "hr", "dl", "dt", "dd", "sup", + "img", "del"] +ALLOWED_ATTRS = bleach.ALLOWED_ATTRIBUTES +ALLOWED_ATTRS["a"] = ["href", "title", "alt"] +ALLOWED_ATTRS["img"] = ["alt", "src"] +ALLOWED_ATTRS["*"] = ["class"] + + def _make_extensions_list(wikilinks_config=None, project=None): return [AutolinkExtension(), AutomailExtension(), @@ -86,12 +112,12 @@ def _get_markdown(project): @cache_by_sha def render(project, text): md = _get_markdown(project) - return md.convert(text) + return bleach.clean(md.convert(text), tags=ALLOWED_TAGS) def render_and_extract(project, text): md = _get_markdown(project) - result = md.convert(text) + result = bleach.clean(md.convert(text), tags=ALLOWED_TAGS) return (result, md.extracted_data) diff --git a/tests/integration/test_mdrender.py b/tests/integration/test_mdrender.py index a905b4c5..700fb465 100644 --- a/tests/integration/test_mdrender.py +++ b/tests/integration/test_mdrender.py @@ -33,7 +33,7 @@ dummy_project.slug = "test" def test_proccessor_valid_user_mention(): factories.UserFactory(username="user1", full_name="test name") result = render(dummy_project, "**@user1**") - expected_result = "
" + expected_result = "" assert result == expected_result diff --git a/tests/unit/test_mdrender.py b/tests/unit/test_mdrender.py index a3ef0c93..81679f88 100644 --- a/tests/unit/test_mdrender.py +++ b/tests/unit/test_mdrender.py @@ -43,7 +43,7 @@ def test_proccessor_valid_us_reference(): instance.content_type.model = "userstory" instance.content_object.subject = "test" result = render(dummy_project, "**#1**") - expected_result = '' + expected_result = '' assert result == expected_result @@ -53,7 +53,7 @@ def test_proccessor_valid_issue_reference(): instance.content_type.model = "issue" instance.content_object.subject = "test" result = render(dummy_project, "**#2**") - expected_result = '' + expected_result = '' assert result == expected_result @@ -63,7 +63,7 @@ def test_proccessor_valid_task_reference(): instance.content_type.model = "task" instance.content_object.subject = "test" result = render(dummy_project, "**#3**") - expected_result = '' + expected_result = '' assert result == expected_result @@ -140,20 +140,20 @@ def test_render_url_automail(): def test_render_absolute_image(): - assert render(dummy_project, "") == "print("test")\n
print(\"test\")\n
print("test")\n
print(\"test\")\n