aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew White <andrew.white@unboxed.co>2018-03-08 14:14:09 +0000
committerAndrew White <andrew.white@unboxed.co>2018-03-08 14:14:09 +0000
commit190744cd8ed014915803fa805996be04dc750d9d (patch)
tree66aca1907aac710c55e710f91392f40c49472b1d
parentaf406a753c59266c61e9ebcd0f131fdc6533a124 (diff)
downloadrails-190744cd8ed014915803fa805996be04dc750d9d.tar.gz
rails-190744cd8ed014915803fa805996be04dc750d9d.tar.bz2
rails-190744cd8ed014915803fa805996be04dc750d9d.zip
Always yield a CSP policy instance
If the app has the CSP disabled globally allow a controller action to enable the policy for that request.
-rw-r--r--actionpack/lib/action_controller/metal/content_security_policy.rb6
-rw-r--r--actionpack/test/dispatch/content_security_policy_test.rb70
-rw-r--r--railties/lib/rails/application_controller.rb6
3 files changed, 65 insertions, 17 deletions
diff --git a/actionpack/lib/action_controller/metal/content_security_policy.rb b/actionpack/lib/action_controller/metal/content_security_policy.rb
index 67682e7f4f..b8fab4ebe3 100644
--- a/actionpack/lib/action_controller/metal/content_security_policy.rb
+++ b/actionpack/lib/action_controller/metal/content_security_policy.rb
@@ -17,7 +17,7 @@ module ActionController #:nodoc:
def content_security_policy(enabled = true, **options, &block)
before_action(options) do
if block_given?
- policy = request.content_security_policy.clone
+ policy = current_content_security_policy
yield policy
request.content_security_policy = policy
end
@@ -44,5 +44,9 @@ module ActionController #:nodoc:
def content_security_policy_nonce
request.content_security_policy_nonce
end
+
+ def current_content_security_policy
+ request.content_security_policy.try(:clone) || ActionDispatch::ContentSecurityPolicy.new
+ end
end
end
diff --git a/actionpack/test/dispatch/content_security_policy_test.rb b/actionpack/test/dispatch/content_security_policy_test.rb
index 205bce16d4..f133aae865 100644
--- a/actionpack/test/dispatch/content_security_policy_test.rb
+++ b/actionpack/test/dispatch/content_security_policy_test.rb
@@ -369,18 +369,6 @@ class ContentSecurityPolicyIntegrationTest < ActionDispatch::IntegrationTest
private
- def env_config
- Rails.application.env_config
- end
-
- def content_security_policy
- env_config["action_dispatch.content_security_policy"]
- end
-
- def content_security_policy=(policy)
- env_config["action_dispatch.content_security_policy"] = policy
- end
-
def assert_policy(expected, report_only: false)
assert_response :success
@@ -396,3 +384,61 @@ class ContentSecurityPolicyIntegrationTest < ActionDispatch::IntegrationTest
assert_equal expected, response.headers[expected_header]
end
end
+
+class DisabledContentSecurityPolicyIntegrationTest < ActionDispatch::IntegrationTest
+ class PolicyController < ActionController::Base
+ content_security_policy only: :inline do |p|
+ p.default_src "https://example.com"
+ end
+
+ def index
+ head :ok
+ end
+
+ def inline
+ head :ok
+ end
+ end
+
+ ROUTES = ActionDispatch::Routing::RouteSet.new
+ ROUTES.draw do
+ scope module: "disabled_content_security_policy_integration_test" do
+ get "/", to: "policy#index"
+ get "/inline", to: "policy#inline"
+ end
+ end
+
+ class PolicyConfigMiddleware
+ def initialize(app)
+ @app = app
+ end
+
+ def call(env)
+ env["action_dispatch.content_security_policy"] = nil
+ env["action_dispatch.content_security_policy_nonce_generator"] = nil
+ env["action_dispatch.content_security_policy_report_only"] = false
+ env["action_dispatch.show_exceptions"] = false
+
+ @app.call(env)
+ end
+ end
+
+ APP = build_app(ROUTES) do |middleware|
+ middleware.use PolicyConfigMiddleware
+ middleware.use ActionDispatch::ContentSecurityPolicy::Middleware
+ end
+
+ def app
+ APP
+ end
+
+ def test_generates_no_content_security_policy_by_default
+ get "/"
+ assert_nil response.headers["Content-Security-Policy"]
+ end
+
+ def test_generates_content_security_policy_header_when_globally_disabled
+ get "/inline"
+ assert_equal "default-src https://example.com", response.headers["Content-Security-Policy"]
+ end
+end
diff --git a/railties/lib/rails/application_controller.rb b/railties/lib/rails/application_controller.rb
index 39f7791c18..b3fe822218 100644
--- a/railties/lib/rails/application_controller.rb
+++ b/railties/lib/rails/application_controller.rb
@@ -7,10 +7,8 @@ class Rails::ApplicationController < ActionController::Base # :nodoc:
before_action :disable_content_security_policy_nonce!
content_security_policy do |policy|
- if policy
- policy.script_src :unsafe_inline
- policy.style_src :unsafe_inline
- end
+ policy.script_src :unsafe_inline
+ policy.style_src :unsafe_inline
end
private