Skip to content

Instantly share code, notes, and snippets.

@seak0503
Last active March 11, 2016 01:11
Show Gist options
  • Save seak0503/48c453e94f73835aaccf to your computer and use it in GitHub Desktop.
Save seak0503/48c453e94f73835aaccf to your computer and use it in GitHub Desktop.
viewで表示する時にエスケープ処理をしつつ、改行すべきところに`<br>`を入れる方法

登録データ

bodyカラムに下記が登録されていると過程する

<script type=”text/javascript”>
alert(“バカ”);
</script>

viewで表示する時にエスケープ処理をしつつ、改行すべきところに<br>を入れる方法を考える

NGパターン

まずはNGパターンをいくつか試す

NGパターン1

  • view
<%= @message.body.gsub(/\n/, '<br />') %>
  • ブラウザ表示
<script type=”text/javascript”> <br />alert(“バカ”); <br /></script>
  • HTMLソース

<%= %>で囲っているので自動的にエスケープされているためjavascriptは実行 されないが、改行して表示したい<br>タグもエスケープされてしまっている。

&lt;script type=”text/javascript”&gt;&lt;br /&gt;alert(“バカ”);&lt;br /&gt;&lt;/script&gt;

NGパターン2

  • view
<%= raw(@message.body.gsub(/\n/, '<br />')) %>
  • ブラウザ表示

rawメソッドにて<%= >が自動で行うエスケープ処理をバイパスしたため、クロスサイトスクリプティングが 発生してしまう。

NGパターン3

  • view
<%= html_escape(@message.body).gsub(/\n/, '<br />') %>
  • ブラウザ表示
&lt;script type=”text/javascript”&gt; <br />alert(“バカ”); <br />&lt;/script&gt;
  • HTMLソース

javascriptの箇所は二重エスケープ(html_escap<%= %>)になっており、 html_escape後に改行コード\nを変換した<br />タグは<%= %>により エスケープされて表示されてしまっている。

&amp;lt;script type=”text/javascript”&amp;gt;&lt;br /&gt;alert(“バカ”);&lt;br /&gt;&amp;lt;/script&amp;gt;

OKパターン

  • view
<%= raw(html_escape(@message.body).gsub(/\n/, '<br />')) %>
  • ブラウザ表示
<script type=”text/javascript”> 
alert(“バカ”); 
</script>
  • HTMLソース

エスケープすべきところhtml_escapeで事前にエスケープし、その後 改行コード\n<br>タグに変換。 表示の際は<%= %>でエスケープ処理がされないように、rawメソッドで 処理している。

&lt;script type=”text/javascript”&gt;<br />alert(“バカ”);<br />&lt;/script&gt;

補足説明

OKパターンのrawメソッドは、自作ビューヘルパ定義や、プレゼンターで利用した方が良く viewでは<%== %>を使った方がシンプルで良いと言われている。 viewで使う場合とプレゼンターで使う場合の例はそれぞれ下記のようになる。

  • view
<%== html_escape(@message.body).gsub(/\n/, '<br />') %>
  • presenter
def formatted_body
  raw(ERB::Util.html_escape(body).gsub(/\n/, '<br />'))
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment