Railsのhtml_safeメソッドとはなにか
html_safe
の挙動
html_safe
は、HTMLをエスケープせずにレンダリングするメソッド。通常だと、Railsは出力される文字列を自動でエスケープして、XSS攻撃を防ぐ。しかし、html_safe
メソッドを使うと、その文字列が安全であると解釈され、エスケープされずそのままHTMLとして表示される。
わざわざRailsが安全のために自動でエスケープ処理をしてくれるところを、html_safe
でエスケープをキャンセルするため、このメソッドを使う場合は非常に慎重になる必要がある。
具体例1
たとえば、以下のようなコードがある場合。
<%= "<strong>Bold Text</strong>" %>
これは、文字列がHTMLタグとして解釈されず、テキストとしてそのまま表示される。Railsがよしなにエスケープしてくれた結果だ。
ちなみに、html_escape
メソッドを実行しても同じ結果になる。
<%= html_escape("<strong>Bold Text</strong>") %>
<!-- 短縮バージョン -->
<%= h("<strong>Bold Text</strong>") %>
html_safe
メソッドを使うと、HTMLタグはエスケープされないので、HTMLタグが反映した形で表示される。
<%= "<strong>Bold Text</strong>".html_safe %>
具体例2
以下のような、ブラウザを操作するためのスクリプトがある場合。
<%= "<script>alert('XSS');</script>" %>
ここでも、Railsは自動でエスケープ処理をするため、スクリプトはスクリプトとして解釈されず、ただのテキストとして表示される。
では、html_safe
メソッドを加えてみるとどうなるか。
<%= "<script>alert('XSS');</script>".html_safe %>
スクリプトが実行されてしまう・・・!こりゃイカン。
APIリファレンスを読む
html_safe
について、公式のAPIリファレンスを読む。
Marks a string as trusted safe. It will be inserted into HTML with no additional escaping performed. It is your responsibility to ensure that the string contains no malicious content. This method is equivalent to the raw helper in views. It is recommended that you use sanitize instead of this method. It should never be called on user input.
https://api.rubyonrails.org/classes/String.html#method-i-html_safe
- 文字列を安全だと解釈する
- HTMLはエスケープされない
- 悪意のあるコンテンツが含まれていないことを確かめる責任があなたにはある
- viewで使う
raw
ヘルパーと同じ機能を持つ - このメソッドよりも
sanitize
メソッドがオススメやで - ユーザーが入力したコンテンツに対して呼ばれるべきではない
ソースコード
ではどうすればいいのか
公式リファレンスがオススメしているとおり、ユーザーがHTMLを入力することが許可されている場合や、特定のHTMLタグや属性を許可したい場合はsanitize
メソッドを使う。
具体例1
<%= sanitize("<strong>Bold Text</strong>") %>
👇 strongタグが反映されている
具体例2
<%= sanitize("<script>alert('XSS');</script>") %>
👇 scriptタグが除去されている
ちなみにsanitizeとは「消毒する」「清潔にする」という意味を持つ。
リファレンスはこちら。
Discussion