From ddb6d788d6a611fd1ba6cf92ad6d1342079517a8 Mon Sep 17 00:00:00 2001 From: "yuuji.yaginuma" Date: Sat, 15 Jun 2019 12:54:26 +0900 Subject: Make `ActionDispatch::Response#content_type` behavior configurable I changed return value of `ActionDispatch::Response#content_type` in #36034. But this change seems to an obstacle to upgrading. https://github.com/rails/rails/pull/36034#issuecomment-498795893 Therefore, I restored the behavior of `ActionDispatch::Response#content_type` to 5.2 and deprecated old behavior. Also, made it possible to control the behavior with the config. --- actionpack/lib/action_dispatch/http/response.rb | 13 ++++++++++++- actionpack/lib/action_dispatch/railtie.rb | 2 ++ 2 files changed, 14 insertions(+), 1 deletion(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb index 63d8f6b585..ea3692951f 100644 --- a/actionpack/lib/action_dispatch/http/response.rb +++ b/actionpack/lib/action_dispatch/http/response.rb @@ -86,6 +86,7 @@ module ActionDispatch # :nodoc: cattr_accessor :default_charset, default: "utf-8" cattr_accessor :default_headers + cattr_accessor :return_only_media_type_on_content_type, default: false include Rack::Response::Helpers # Aliasing these off because AD::Http::Cache::Response defines them. @@ -243,7 +244,17 @@ module ActionDispatch # :nodoc: # Content type of response. def content_type - super.presence + if self.class.return_only_media_type_on_content_type + ActiveSupport::Deprecation.warn( + "Rails 6.1 will return Content-Type header without modification." \ + " If you want just the MIME type, please use `#media_type` instead." + ) + + content_type = super + content_type ? content_type.split(/;\s*charset=/)[0].presence : content_type + else + super.presence + end end # Media type of response. diff --git a/actionpack/lib/action_dispatch/railtie.rb b/actionpack/lib/action_dispatch/railtie.rb index 5f711c7348..66f90980b9 100644 --- a/actionpack/lib/action_dispatch/railtie.rb +++ b/actionpack/lib/action_dispatch/railtie.rb @@ -23,6 +23,7 @@ module ActionDispatch config.action_dispatch.use_authenticated_cookie_encryption = false config.action_dispatch.use_cookies_with_metadata = false config.action_dispatch.perform_deep_munge = true + config.action_dispatch.return_only_media_type_on_content_type = true config.action_dispatch.default_headers = { "X-Frame-Options" => "SAMEORIGIN", @@ -43,6 +44,7 @@ module ActionDispatch ActionDispatch::Request::Utils.perform_deep_munge = app.config.action_dispatch.perform_deep_munge ActionDispatch::Response.default_charset = app.config.action_dispatch.default_charset || app.config.encoding ActionDispatch::Response.default_headers = app.config.action_dispatch.default_headers + ActionDispatch::Response.return_only_media_type_on_content_type = app.config.action_dispatch.return_only_media_type_on_content_type ActionDispatch::ExceptionWrapper.rescue_responses.merge!(config.action_dispatch.rescue_responses) ActionDispatch::ExceptionWrapper.rescue_templates.merge!(config.action_dispatch.rescue_templates) -- cgit v1.2.3 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. --- .../http/content_security_policy.rb | 29 +++++++++++++++------- 1 file changed, 20 insertions(+), 9 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/http/content_security_policy.rb b/actionpack/lib/action_dispatch/http/content_security_policy.rb index 5c6fa2dfa7..7dedecef34 100644 --- a/actionpack/lib/action_dispatch/http/content_security_policy.rb +++ b/actionpack/lib/action_dispatch/http/content_security_policy.rb @@ -22,8 +22,9 @@ module ActionDispatch #:nodoc: if policy = request.content_security_policy nonce = request.content_security_policy_nonce + nonce_directives = request.content_security_policy_nonce_directives context = request.controller_instance || request - headers[header_name(request)] = policy.build(context, nonce) + headers[header_name(request)] = policy.build(context, nonce, nonce_directives) end response @@ -54,6 +55,7 @@ module ActionDispatch #:nodoc: POLICY_REPORT_ONLY = "action_dispatch.content_security_policy_report_only" NONCE_GENERATOR = "action_dispatch.content_security_policy_nonce_generator" NONCE = "action_dispatch.content_security_policy_nonce" + NONCE_DIRECTIVES = "action_dispatch.content_security_policy_nonce_directives" def content_security_policy get_header(POLICY) @@ -79,6 +81,14 @@ module ActionDispatch #:nodoc: set_header(NONCE_GENERATOR, generator) end + def content_security_policy_nonce_directives + get_header(NONCE_DIRECTIVES) + end + + def content_security_policy_nonce_directives=(generator) + set_header(NONCE_DIRECTIVES, generator) + end + def content_security_policy_nonce if content_security_policy_nonce_generator if nonce = get_header(NONCE) @@ -131,9 +141,9 @@ module ActionDispatch #:nodoc: worker_src: "worker-src" }.freeze - NONCE_DIRECTIVES = %w[script-src style-src].freeze + DEFAULT_NONCE_DIRECTIVES = %w[script-src style-src].freeze - private_constant :MAPPINGS, :DIRECTIVES, :NONCE_DIRECTIVES + private_constant :MAPPINGS, :DIRECTIVES, :DEFAULT_NONCE_DIRECTIVES attr_reader :directives @@ -202,8 +212,9 @@ module ActionDispatch #:nodoc: end end - def build(context = nil, nonce = nil) - build_directives(context, nonce).compact.join("; ") + def build(context = nil, nonce = nil, nonce_directives = nil) + nonce_directives = DEFAULT_NONCE_DIRECTIVES if nonce_directives.nil? + build_directives(context, nonce, nonce_directives).compact.join("; ") end private @@ -226,10 +237,10 @@ module ActionDispatch #:nodoc: end end - def build_directives(context, nonce) + def build_directives(context, nonce, nonce_directives) @directives.map do |directive, sources| if sources.is_a?(Array) - if nonce && nonce_directive?(directive) + if nonce && nonce_directive?(directive, nonce_directives) "#{directive} #{build_directive(sources, context).join(' ')} 'nonce-#{nonce}'" else "#{directive} #{build_directive(sources, context).join(' ')}" @@ -264,8 +275,8 @@ module ActionDispatch #:nodoc: end end - def nonce_directive?(directive) - NONCE_DIRECTIVES.include?(directive) + def nonce_directive?(directive, nonce_directives) + nonce_directives.include?(directive) end end end -- cgit v1.2.3 From b21ef266619074c27f0ea147f5ebaccfe1709ecf Mon Sep 17 00:00:00 2001 From: John Hawthorn Date: Wed, 3 Jul 2019 11:23:55 -0700 Subject: Preload browser driver_path for system testing The webdrivers gem configures Selenium::WebDriver::Service.driver_path as a proc which updates the web drivers and returns their path. This commit introduces SystemTesting::Browser#preload, which runs this proc early. This ensures that webdrivers update is run before forking for parallel testing, but doesn't explicitly tie us to that gem (and I think anything configured as driver_path probably makes sense to eager-load). --- actionpack/lib/action_dispatch/system_test_case.rb | 1 + actionpack/lib/action_dispatch/system_testing/browser.rb | 13 +++++++++++++ actionpack/lib/action_dispatch/system_testing/driver.rb | 2 ++ 3 files changed, 16 insertions(+) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/system_test_case.rb b/actionpack/lib/action_dispatch/system_test_case.rb index a7fb5fa330..29864c0f8e 100644 --- a/actionpack/lib/action_dispatch/system_test_case.rb +++ b/actionpack/lib/action_dispatch/system_test_case.rb @@ -4,6 +4,7 @@ gem "capybara", ">= 2.15" require "capybara/dsl" require "capybara/minitest" +require "selenium/webdriver" require "action_controller" require "action_dispatch/system_testing/driver" require "action_dispatch/system_testing/browser" diff --git a/actionpack/lib/action_dispatch/system_testing/browser.rb b/actionpack/lib/action_dispatch/system_testing/browser.rb index c34907b6cb..f5f195d876 100644 --- a/actionpack/lib/action_dispatch/system_testing/browser.rb +++ b/actionpack/lib/action_dispatch/system_testing/browser.rb @@ -39,6 +39,19 @@ module ActionDispatch end end + # driver_path can be configured as a proc. The webdrivers gem uses this + # proc to update web drivers. Running this proc early allows us to only + # update the webdriver once and avoid race conditions when using + # parallel tests. + def preload + case type + when :chrome + ::Selenium::WebDriver::Chrome::Service.driver_path.try(:call) + when :firefox + ::Selenium::WebDriver::Firefox::Service.driver_path.try(:call) + end + end + private def headless_chrome_browser_options capabilities.args << "--headless" diff --git a/actionpack/lib/action_dispatch/system_testing/driver.rb b/actionpack/lib/action_dispatch/system_testing/driver.rb index 25a09dd918..15943a55ea 100644 --- a/actionpack/lib/action_dispatch/system_testing/driver.rb +++ b/actionpack/lib/action_dispatch/system_testing/driver.rb @@ -9,6 +9,8 @@ module ActionDispatch @screen_size = options[:screen_size] @options = options[:options] @capabilities = capabilities + + @browser.preload end def use -- cgit v1.2.3 From cd4541a1aa7f306d59d167fade17dff17d57ac75 Mon Sep 17 00:00:00 2001 From: John Hawthorn Date: Thu, 4 Jul 2019 14:47:21 -0700 Subject: Fix Browser#preload for older Selenium Older versions of selenium had driver_path on ::Selenium::WebDriver::Chrome directly, not on Service. This avoids errors on those old versions and will preload properly if webdrivers is installed. --- actionpack/lib/action_dispatch/system_testing/browser.rb | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/system_testing/browser.rb b/actionpack/lib/action_dispatch/system_testing/browser.rb index f5f195d876..e861e52f09 100644 --- a/actionpack/lib/action_dispatch/system_testing/browser.rb +++ b/actionpack/lib/action_dispatch/system_testing/browser.rb @@ -46,9 +46,19 @@ module ActionDispatch def preload case type when :chrome - ::Selenium::WebDriver::Chrome::Service.driver_path.try(:call) + if ::Selenium::WebDriver::Service.respond_to? :driver_path= + ::Selenium::WebDriver::Chrome::Service.driver_path.try(:call) + else + # Selenium <= v3.141.0 + ::Selenium::WebDriver::Chrome.driver_path + end when :firefox - ::Selenium::WebDriver::Firefox::Service.driver_path.try(:call) + if ::Selenium::WebDriver::Service.respond_to? :driver_path= + ::Selenium::WebDriver::Firefox::Service.driver_path.try(:call) + else + # Selenium <= v3.141.0 + ::Selenium::WebDriver::Firefox.driver_path + end end end -- cgit v1.2.3