気になったのでちょっと調べてみました。
import markdown
とあるので、Python-markdownを使っていることを想定しています。
※以下は、自分の中での考え方の整理も兼ねています(回答としての結論は最後)
前提としてsafeフィルターは外せない
Djangoの挙動として、変数出力は特に指定がなければエスケープされたものが出ます。
そのため、自身で用意したHTMLをそのままHTMLとして出力するためには、autoescape
ブロックかsafe
フィルタによる一時的なエスケープ解除が必須です。
そのため、ユーザーコンテンツなどをDjango経由で出力するのであれば、事前に無害なHTMLにした上で非エスケープ状態で出力しないといけません。
Python-markdown自体はエスケープしない
どうも、以前のPython-markdownにはエスケープすると思わしきsafe_mode
,html_replacement_text
というオプションがあったみたいです。
※ただし、試してみたら自分の想定とも違う挙動だったので「あった」という事実のみに留めておきます。
現在、Python-markdownドキュメントのChangelogを見ると、「サニタイズをしたいなら、bleachというライブラリを使え」という案内が出ています。
ドキュメントのサンプルコードを現実に合わせる
ドキュメントにはコードサンプルもあるのですが、使っているものがちょっと古いようです。
現在では、
- サニタイズ行うライブラリ
bleach
- bleach用の便利なサポートライブラリ
bleach-allowlist
を組み合わせるとちょうどよい感じがします。
Djangoでの利用例
bleach
の非サニタイズ条件をprint_tags
(ブラウザに直接出力しないもののみサニタイズ?)させるケース
(Django上での確認はしていません。bleachの挙動でエスケープしたことだけ確認しています)
diff
1from django import template
2from django.template.defaultfilters import stringfilter
3import markdown
4+import bleach
5+from bleach_allowlist import print_tags
6
7register = template.Library()
8
9@register.filter
10@stringfilter
11def markdown_html(value):
12- return markdown.markdown(value)
13+ return bleach.clean(markdown.markdown(value), print_tags)
※このコードをベースにどれだけサニタイズするかは、要件によって変わってきます
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。