From 09d55b302266cf002a4b307f8d37a105d2838a18 Mon Sep 17 00:00:00 2001 From: "yuuji.yaginuma" Date: Sun, 3 Feb 2019 11:33:44 +0900 Subject: Add the ability to set the CSP nonce only to the specified directives I changed to set CSP nonce to `style-src` directive in #32932. But this causes an issue when `unsafe-inline` is specified to `style-src` (If a nonce is present, a nonce takes precedence over `unsafe-inline`). So, I fixed to nonce directives configurable. By configure this, users can make CSP as before. Fixes #35137. --- railties/lib/rails/application.rb | 3 +- railties/lib/rails/application/configuration.rb | 5 ++-- .../initializers/content_security_policy.rb.tt | 3 ++ .../application/content_security_policy_test.rb | 32 ++++++++++++++++++++++ 4 files changed, 40 insertions(+), 3 deletions(-) (limited to 'railties') diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index dd1770f0ea..225152c50b 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -270,7 +270,8 @@ module Rails "action_dispatch.use_cookies_with_metadata" => config.action_dispatch.use_cookies_with_metadata, "action_dispatch.content_security_policy" => config.content_security_policy, "action_dispatch.content_security_policy_report_only" => config.content_security_policy_report_only, - "action_dispatch.content_security_policy_nonce_generator" => config.content_security_policy_nonce_generator + "action_dispatch.content_security_policy_nonce_generator" => config.content_security_policy_nonce_generator, + "action_dispatch.content_security_policy_nonce_directives" => config.content_security_policy_nonce_directives ) end end diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index 72c7ff169f..f5456f4916 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -18,8 +18,8 @@ module Rails :session_options, :time_zone, :reload_classes_only_on_change, :beginning_of_week, :filter_redirect, :x, :enable_dependency_loading, :read_encrypted_secrets, :log_level, :content_security_policy_report_only, - :content_security_policy_nonce_generator, :require_master_key, :credentials, - :disable_sandbox, :add_autoload_paths_to_load_path + :content_security_policy_nonce_generator, :content_security_policy_nonce_directives, + :require_master_key, :credentials, :disable_sandbox, :add_autoload_paths_to_load_path attr_reader :encoding, :api_only, :loaded_config_version, :autoloader @@ -60,6 +60,7 @@ module Rails @content_security_policy = nil @content_security_policy_report_only = false @content_security_policy_nonce_generator = nil + @content_security_policy_nonce_directives = nil @require_master_key = false @loaded_config_version = nil @credentials = ActiveSupport::OrderedOptions.new diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/content_security_policy.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/initializers/content_security_policy.rb.tt index c517b0f96b..3d468f7633 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/initializers/content_security_policy.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/content_security_policy.rb.tt @@ -23,6 +23,9 @@ # If you are using UJS then enable automatic nonce generation # Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) } +# Set the nonce only to specific directives +# Rails.application.config.content_security_policy_nonce_directives = %w(script-src) + # Report CSP violations to a specified URI # For further information see the following documentation: # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only diff --git a/railties/test/application/content_security_policy_test.rb b/railties/test/application/content_security_policy_test.rb index 3338bcb47d..0bb6ee917a 100644 --- a/railties/test/application/content_security_policy_test.rb +++ b/railties/test/application/content_security_policy_test.rb @@ -119,6 +119,38 @@ module ApplicationTests assert_policy "default-src 'self' https:", report_only: true end + test "global content security policy nonce directives in an initializer" do + controller :pages, <<-RUBY + class PagesController < ApplicationController + def index + render html: "

Welcome to Rails!

" + end + end + RUBY + + app_file "config/initializers/content_security_policy.rb", <<-RUBY + Rails.application.config.content_security_policy do |p| + p.default_src :self, :https + p.script_src :self, :https + p.style_src :self, :https + end + + Rails.application.config.content_security_policy_nonce_generator = proc { "iyhD0Yc0W+c=" } + Rails.application.config.content_security_policy_nonce_directives = %w(script-src) + RUBY + + app_file "config/routes.rb", <<-RUBY + Rails.application.routes.draw do + root to: "pages#index" + end + RUBY + + app("development") + + get "/" + assert_policy "default-src 'self' https:; script-src 'self' https: 'nonce-iyhD0Yc0W+c='; style-src 'self' https:" + end + test "override content security policy in a controller" do controller :pages, <<-RUBY class PagesController < ApplicationController -- cgit v1.2.3