箱のプログラミング日記。

渋谷の自社開発企業でRails書いてます。

html_safeとsanitizeの違い

f:id:y_hakoiri:20191102121915j:plain

DBに保存した文字列の改行を反映させたいと思ってググったら、今まで見たことのあるhtml_safeの他にsanitizeというものが出てきて違いが気になったので比べてみた。

エスケープとは

まず、そもそも日頃よく目にする「エスケープ処理」について改めておさらい。

エスケープ処理とは、マークアップ言語やプログラミング言語で文字列を扱う際に、その言語の文法や処理系にとって特別な意味や機能を持つ文字や記号(およびその並び)を、一定の規則に従って別の文字列に置き換えること。

引用元:エスケープ処理とは - IT用語辞典 e-Words

エスケープ自体がHTMLの文字列を変換するものだと思ってたけど、別にHTMLに限った話ではないみたい。

「一定の規則に従って」とあるので、HTMLの場合は(タグが意味をなさないように)例えば「<」や「>」を「&lt;」「&gt;」と変換するよう決められている。

なぜエスケープが必要なのか

脆弱性攻撃対策のため。

HTMLの場合、例えばRailsで作られたアプリケーションの何かしらのフォームに、悪意のあるユーザーが<script>悪意のあるコード</script>みたいな文字列を意図的に仕組んだとする。

DBに保存されたその文字列がアプリケーション内のどこかで表示されたとき、そのまま表示してしまうとscriptタグとして認識され、中身の悪意のあるコードが実行されてしまう。

悪意のあるコードによりセキュリティが犯されたり、アプリケーションが落とされたりしてしまうのを防ぐために、文字列の中に含まれるHTMLタグをエスケープする(タグとして認識せずscriptタグが発火するのを防ぐ)必要がある。

RailsではデフォルトでHTMLがエスケープされるようになっているので、HTMLタグをそのままタグとして認識させたい時(=改行を反映させたい時など)はhtml_safeやsanitizeなどのヘルパーを使ってエスケープ回避をする必要がある。

html_safeとsanitizeの違い

やっと本題。

結論から言うと、

  • 完全にエスケープを回避したい場合はhtml_safe
  • ある程度タグをそのまま出したいものの危険なタグは出力しないようにしたい場合にはsanitize

という使い分けが良い。

改行を反映させたいからといって迂闊にhtml_safeを使用してしまうと、先ほどの例<script>悪意のあるコード</script>のように悪意のあるscriptタグが含まれていてもそれをエスケープせず表示させてしまうので脆弱性に問題がある。

ユーザーに入力させた内容を安全に、かつ見た目を整えたい場合にはsanitizeを使って、危険なタグはエスケープしながらもHTMLを反映させるのが良さそう。

まとめ

「改行を反映させたいから」html_safeを使うのではなくて、Railsがデフォルトでやってくれているエスケープ処理を回避するためにhtml_safeを使う、という認識ができるようになった。

正直なんのためにエスケープするのかも、今まで説明できるほどは理解できていなかったので、すごく勉強になりました。

参考:現場で使える Ruby on Rails 5速習実践ガイド