##// END OF EJS Templates
lib: use bleach to sanitize HTML generated from markdown - fix XSS issue when repo front page shows README.md...
Mads Kiilerich -
r7322:5746cc3b stable
parent child Browse files
Show More
@@ -31,6 +31,7 b' import logging'
31 import traceback
31 import traceback
32
32
33 import markdown as markdown_mod
33 import markdown as markdown_mod
34 import bleach
34
35
35 from kallithea.lib.utils2 import safe_unicode, MENTIONS_REGEX
36 from kallithea.lib.utils2 import safe_unicode, MENTIONS_REGEX
36
37
@@ -142,28 +143,40 b' class MarkupRenderer(object):'
142 @classmethod
143 @classmethod
143 def markdown(cls, source, safe=True, flavored=False):
144 def markdown(cls, source, safe=True, flavored=False):
144 """
145 """
145 Convert Markdown (possibly GitHub Flavored) to HTML, possibly
146 Convert Markdown (possibly GitHub Flavored) to XSS safe HTML, possibly
146 with "safe" fall-back to plaintext.
147 with "safe" fall-back to plaintext.
147
148
148 >>> MarkupRenderer.markdown('''<img id="a" style="margin-top:-1000px;color:red" src="http://example.com/test.jpg">''')
149 >>> MarkupRenderer.markdown('''<img id="a" style="margin-top:-1000px;color:red" src="http://example.com/test.jpg">''')
149 u'<p><img id="a" style="margin-top:-1000px;color:red" src="http://example.com/test.jpg"></p>'
150 u'<p><img id="a" src="http://example.com/test.jpg" style="color: red;"></p>'
150 >>> MarkupRenderer.markdown('''<img class="c d" src="file://localhost/test.jpg">''')
151 >>> MarkupRenderer.markdown('''<img class="c d" src="file://localhost/test.jpg">''')
151 u'<p><img class="c d" src="file://localhost/test.jpg"></p>'
152 u'<p><img class="c d"></p>'
152 >>> MarkupRenderer.markdown('''<a href="foo">foo</a>''')
153 >>> MarkupRenderer.markdown('''<a href="foo">foo</a>''')
153 u'<p><a href="foo">foo</a></p>'
154 u'<p><a href="foo">foo</a></p>'
154 >>> MarkupRenderer.markdown('''<script>alert(1)</script>''')
155 >>> MarkupRenderer.markdown('''<script>alert(1)</script>''')
155 u'<script>alert(1)</script>'
156 u'&lt;script&gt;alert(1)&lt;/script&gt;'
156 >>> MarkupRenderer.markdown('''<div onclick="alert(2)">yo</div>''')
157 >>> MarkupRenderer.markdown('''<div onclick="alert(2)">yo</div>''')
157 u'<div onclick="alert(2)">yo</div>'
158 u'<div>yo</div>'
158 >>> MarkupRenderer.markdown('''<a href="javascript:alert(3)">yo</a>''')
159 >>> MarkupRenderer.markdown('''<a href="javascript:alert(3)">yo</a>''')
159 u'<p><a href="javascript:alert(3)">yo</a></p>'
160 u'<p><a>yo</a></p>'
160 """
161 """
161 source = safe_unicode(source)
162 source = safe_unicode(source)
162 try:
163 try:
163 if flavored:
164 if flavored:
164 source = cls._flavored_markdown(source)
165 source = cls._flavored_markdown(source)
165 markdown_html = markdown_mod.markdown(source, ['codehilite', 'extra'])
166 markdown_html = markdown_mod.markdown(source, ['codehilite', 'extra'])
166 return markdown_html
167 # Allow most HTML, while preventing XSS issues:
168 # no <script> tags, no onclick attributes, no javascript
169 # "protocol", and also limit styling to prevent defacing.
170 return bleach.clean(markdown_html,
171 tags=['a', 'abbr', 'b', 'blockquote', 'br', 'code', 'dd',
172 'div', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5',
173 'h6', 'hr', 'i', 'img', 'li', 'ol', 'p', 'pre', 'span',
174 'strong', 'sub', 'sup', 'table', 'tbody', 'td', 'th',
175 'thead', 'tr', 'ul'],
176 attributes=['class', 'id', 'style', 'label', 'title', 'alt', 'href', 'src'],
177 styles=['color'],
178 protocols=['http', 'https', 'mailto'],
179 )
167 except Exception:
180 except Exception:
168 log.error(traceback.format_exc())
181 log.error(traceback.format_exc())
169 if safe:
182 if safe:
@@ -57,6 +57,7 b' requirements = ['
57 "Routes==1.13",
57 "Routes==1.13",
58 "dulwich>=0.9.9,<=0.9.9",
58 "dulwich>=0.9.9,<=0.9.9",
59 "mercurial>=2.9,<4.3",
59 "mercurial>=2.9,<4.3",
60 "bleach >= 3.0, < 3.1",
60 ]
61 ]
61
62
62 if sys.version_info < (2, 7):
63 if sys.version_info < (2, 7):
General Comments 0
You need to be logged in to leave comments. Login now