From c83ffa8529b87fc2946e727a6c4f4f527149f9a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Fri, 31 Oct 2014 09:51:23 +0100 Subject: [PATCH] Fix issue #1500: Now generated html is escaped --- requirements.txt | 1 + taiga/mdrender/service.py | 30 ++++++++++++++++++++++++++++-- tests/integration/test_mdrender.py | 2 +- tests/unit/test_mdrender.py | 14 +++++++------- 4 files changed, 37 insertions(+), 10 deletions(-) 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 = "

@user1

" + expected_result = "

@user1

" 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 = '

#1

' + expected_result = '

#1

' 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 = '

#2

' + expected_result = '

#2

' 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 = '

#3

' + expected_result = '

#3

' assert result == expected_result @@ -140,20 +140,20 @@ def test_render_url_automail(): def test_render_absolute_image(): - assert render(dummy_project, "![test](/test.png)") == "

\"test\"

" + assert render(dummy_project, "![test](/test.png)") == "

\"test\"

" def test_render_relative_image(): - assert render(dummy_project, "![test](test.png)") == "

\"test\"

" + assert render(dummy_project, "![test](test.png)") == "

\"test\"

" def test_render_triple_quote_code(): - expected_result = "
print("test")\n
" + expected_result = "
print(\"test\")\n
" assert render(dummy_project, "```\nprint(\"test\")\n```") == expected_result def test_render_triple_quote_and_lang_code(): - expected_result = "
print("test")\n
" + expected_result = "
print(\"test\")\n
" assert render(dummy_project, "```python\nprint(\"test\")\n```") == expected_result