XSSについてゆとりだったのでSinatraとERBでおさらいすることにした

慣れとは怖いものだ……惰性でテンプレートエンジンとかFWとか選んじゃいけない。
反省と復習を兼ねておさらいして、対応したメモを残す。

おさらいしようと思った経緯

「HTMLをエスケープしないでそのまま表示させたらまずいでしょ(へんなスクリプト仕込まれたらヤバい)」っていう認識はありつつ、ずっとRailsやSlim、Hamlといった「自動でHTMLをよしなにエスケープしてくれる環境」でコーディングしていた。
なんでも自動的によしなにしてくれるのはとても助かる。わざわざ考えなくても勝手に実装してくれるのは忙しい時の強い味方。
一方、もし「自動でよしなに対策してくれるものが使えない」時に、「当たり前にやってくれてるものだと思っていた」という思い込みから対応が漏れてしまうということも起こる。
そして先日、まんまと対応が漏れそうになった……という状況に近いことがあった。

Sinatraでメモアプリを作っていた。
テンプレートエンジンは使い慣れているという理由でSlimを使っていたが、メンターさんに「Slim使っているの、XSS対応もできるので良いですね!」って褒められたけど、「あー、そのへんのことあんまり考えずに使ってましたわ…」となった。

エスケープして表示するようにしないとまずいという認識はあったけど、それを理由にSlimを使ってたわけではなかった。
Slimが勝手にエスケープしてくれるから、当然?手元でわざわざスクリプト仕込んで確認してみたりとかもしてなかったし……(しないとダメでしょってツッコまれるところ)。

経緯長すぎ。

自動でエスケープしてくれないテンプレートエンジンを使う

ERBを使う。
5億年ぶりくらいで、書き方を忘れたのでggりながら思い出しながら書く。
Slimで作ってたテンプレートをERBに直すのがめちゃくちゃめんどくさかった……なにこれ、もう二度と使いたくない。

エスケープするためのヘルパーメソッドを用意する

  • Sinatraのhelpersを使って、エスケープしてくれるヘルパーメソッドを作る
  • エスケープはRubyの標準ライブラリERB::Utilを使う
    • Sinatraに入ってるRackを使う方法もQiita記事で見つけたけど、Rackの公式ドキュメントを探してもエスケープしてくれるメソッドに関しての情報が探しきれなかったので、使わないことにした。
    • 多分、探せばどっかにあると思うけど、ここでそんなに時間使うのもな…と思った

sinatrarb.com

docs.ruby-lang.org

注釈
2.7のドキュメントを参照しているのは「自分が使ってる環境はまだ2.7のままだから」っていう理由です。
着手してたのが2020年末で、Ruby3.0になってまもなくまだ手を出してなかったっていうだけです…。

require 'erb'
include ERB::Util

# 中略

helpers do
  def h(text)
    escape_html(text)
  end
end

エスケープしてるところ

via GIPHY

余談

改行は有効にしたいと思ったけどここではXSS対応が主目的なので、今回は無視した。

反省文

  • テンプレートエンジンやFWとか選ぶときはセキュリティにも目を向ける
  • でもERBはもう使いたくない。Slim is 楽。