ある日、開発で使用しているgemのlayoutファイルに以下のようなコードを見かけました。
<%= javascript_tag nonce: true do %>
javascript_tag
にnonce: true
のオプションが渡されています。
「なんぞこれ?」となったのでとりあえずnonceに関して調べてみました。
nonceについて
scriptタグに付与することができるnonce属性は、XSS攻撃などで不正なスクリプトが実行されることを防ぐために利用されます。
nonceは"number used once"の略で、一度だけ使用される数値を意味しています。
scriptタグに設定されたnonce属性には以下のような使い捨ての乱数を設定し、ページを読み込むたびに異なる乱数が再設定されるようにします。
<script nonce="8IBTHwOdqNKAWeKl7plt8g==">
// …
</script>
さらに、nonceに設定した乱数と同じ値をContent-Security-Policy
ヘッダーで送信するようにします。
そうすることでContent-Security-Policy
ヘッダーに設定されたnonce値が設定されたscriptのみを実行対象とし、正規のnonce値を持たないscriptは実行されなくなります。
Content-Security-Policy: script-src 'nonce-8IBTHwOdqNKAWeKl7plt8g=='
Railsでnonceを使う
Railsでnonceを利用したい場合は以下の設定をconfig/initializers/content_security_policy.rb
に記載します。
Rails.application.config.content_security_policy do |policy|
policy.script_src :self, :https
end
Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) }
これで以下のようにjavascript_tag
にnonce: ture
を渡せばnonce値が自動的に追加され、実行されるスクリプトを制限することができるようになります。
<%= javascript_tag nonce: true do -%>
alert('Hello, World!');
<% end -%>
ちなみに以下のメソッドでnonceに設定されている乱数を取得することもできます。
request.content_security_policy_nonce
=> "3xdpMsDFBsRpwY8KQp//LQ=="