Madogiwa Blog

主に技術系の学習メモに使っていきます。

Ruby on Rails: Content Security Policyを使ってみたのでMEMO

Ruby on Rails 5.2からContent Security Policyヘッダーを設定するDSLが提供されました。

2.5 Content Security Policy
Rails 5.2 ships with a new DSL that allows you to configure a Content Security Policy for your application. You can configure a global default policy and then override it on a per-resource basis and even use lambdas to inject per-request values into the header such as account subdomains in a multi-tenant application. You can read more about this in the Securing Rails Applications guide.
Ruby on Rails 5.2 Release Notes — Ruby on Rails Guides

今更ながら個人のサービスに適用してみたので使い方とかをメモ📝

Content Security Policyとは?

HTTP の Content-Security-Policy レスポンスヘッダーは、ウェブサイト管理者が、あるページにユーザーエージェントが読み込みを許可されたリソースを管理できるようにします。いくつかの例外を除いて、大半のポリシーにはサーバーオリジンとスクリプトエンドポイントの指定を含んでいます。これはクロスサイトスクリプティング攻撃 (クロスサイトスクリプティング) を防ぐのに役立ちます。 Content-Security-Policy - HTTP | MDN

上述の通りレンスポンスヘッダーでクライアントがロードするリソースの許可条件を設定できる機能ようです。

CSP を有効にするには、ウェブサーバーから Content-Security-Policy HTTP ヘッダーを返すように設定する必要があります 他にも、 要素を用いてポリシーを指定することも可能です。例を挙げます。 コンテンツセキュリティポリシー (CSP) - HTTP | MDN

設定するにはHTTPヘッダーまたはmetaタグでポリシーに記述することで行えます。

# HTTPヘッダーでContent-Security-Policyを返すようにする
Content-Security-Policy: default-src 'self'
# or metaタグを設定する
<meta http-equiv="Content-Security-Policy" content="default-src 'self' />

Ruby on RailsでContent Security Policyを設定する

Ruby on RailsではDSLを使ってContent-Security-Policy HTTP ヘッダーの内容及びCSP関連の振る舞いを指定することができます。

Rails.application.configure do
  config.content_security_policy do |policy|
    policy.default_src :self, :https # 同一オリジン OR httpsで取得するリソースのみ許可
    policy.script_src :strict_dynamic # nonceにより検証が成功したリソースのみを許可
  end

  # Generate session nonces for permitted importmap and inline scripts
  config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s } # session_idをnonceの取得元として使用する
  config.content_security_policy_nonce_directives = %w[script-src] # JavaScriptはnonceによる検証の対象にする

  # Report CSP violations to a specified URI. See:
  # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only
  config.content_security_policy_report_only = true # CSP違反があってもエラーとしない
end

cssstrict_dynamicにしたい場合にはpolicy.style_src :strict_dynamicにし、content_security_policy_nonce_directives = %w[script-src style-src]を指定するようにすれば良い。 ※ Viteを利用している場合には制約上、script_src: unsafe-eval, style_src: unsafe-inlineを許可する必要がある(?)ようです Link

nonceの付与はjavascript_include_tag等であればnonce: trueを指定すれば自動的に付与できますが、 scriptタグを直接記載しているときにはcontent_security_policy_noncenonceを取得することもできるので直接指定することもできます。

<script nonce="<%= content_security_policy_nonce %>">

おわりに

Ruby on Rails、こういうのを簡単に指定できて非常に便利ですね 🚃

参考

zenn.dev

railsguides.jp