あまブログ

ドキドキ......ドキドキ2択クイ〜〜〜〜〜〜〜ズ!!

【Rails】タグのエスケープ & 連続した改行の反映

結論

safe_joinを使えば、タグをエスケープしてXSS攻撃を防ぎつつ、連続した改行も反映される。

<% text = "1行目\n\n\n2行目<script>alert()</script>" %>
<%= safe_join(text.split("\n"), tag.br) %>

# 1行目
# 
# 
# 2行目<script>alert()</script>

結論に至るまでの道のり

その1

<% text = "1行目\n\n\n2行目<script>alert()</script>" %>
<%= text.gsub("\n", '<br>').html_safe %>

# 1行目
# 2行目
  • ❌タグのエスケープ
  • ❌連続した改行の反映

連続した改行は反映されないし、alert()が実行されてしまう。

その2

<% text = "1行目\n\n\n2行目<script>alert()</script>" %>
<%= html_escape(text).gsub("\n", '<br>').html_safe %>

# 1行目
# 
# 
# 2行目<script>alert()</script>
  • ✅タグのエスケープ
  • ✅連続した改行の反映

しかし、これだとrubocopのRails/OutputSafetyで怒られる。

またRails API:String#html_safeにもあるように、html_safe()をユーザー入力に対して使うのは非推奨とされている。

その3

<% text = "1行目\n\n\n2行目<script>alert()</script>" %>
<%= simple_format(html_escape(text)) %>

# 1行目
# 
# 2行目<script>alert()</script>
  • ✅タグのエスケープ
  • ❌連続した改行の反映

改行が1つにまとめられてしまう。

その4

<% text = "1行目\n\n\n2行目<script>alert()</script>" %>
<%= safe_join(text.split("\n"), tag.br) %>

# 1行目
# 
# 
# 2行目<script>alert()</script>
  • ✅タグのエスケープ
  • ✅連続した改行の反映

結論、タグのエスケープと連続した改行の反映を行いたい場合は、safe_joinを使おう。


【参考】