diff --git a/app/controllers/concerns/inline_script_hashes.rb b/app/controllers/concerns/inline_script_hashes.rb index c0fde41..bf2761e 100644 --- a/app/controllers/concerns/inline_script_hashes.rb +++ b/app/controllers/concerns/inline_script_hashes.rb @@ -8,7 +8,9 @@ module InlineScriptHashes ENTRY_POINT_SCRIPT = %(import "application") included do - content_security_policy do |policy| + # With the policy turned off there's nothing to add to, so leave the + # request without one rather than starting an empty policy + content_security_policy if: -> { request.content_security_policy } do |policy| if sources = policy.directives["script-src"] importmap = Rails.application.importmap.to_json(resolver: helpers) policy.directives["script-src"] = sources | script_origins(importmap) | script_hashes(importmap, ENTRY_POINT_SCRIPT) diff --git a/test/integration/content_security_policy_test.rb b/test/integration/content_security_policy_test.rb index 7e78d38..3f0eac7 100644 --- a/test/integration/content_security_policy_test.rb +++ b/test/integration/content_security_policy_test.rb @@ -55,6 +55,16 @@ class ContentSecurityPolicyTest < ActionDispatch::IntegrationTest end end + test "with the policy turned off, pages send none" do + without_policy do + get PAGE_PATH + follow_redirect! while response.redirect? + + assert_response :success + assert_nil response.headers["Content-Security-Policy"] + end + end + test "the escape hatch boots without a policy" do output = IO.popen({ "DISABLE_CONTENT_SECURITY_POLICY" => "true" }, [ "bin/rails", "runner", "print Rails.application.config.content_security_policy.inspect" ], chdir: Rails.root, err: File::NULL, &:read) @@ -67,6 +77,14 @@ class ContentSecurityPolicyTest < ActionDispatch::IntegrationTest end private + # What DISABLE_CONTENT_SECURITY_POLICY=true leaves at boot: no application policy + def without_policy + previous = Rails.application.env_config.delete("action_dispatch.content_security_policy") + yield + ensure + Rails.application.env_config["action_dispatch.content_security_policy"] = previous + end + def with_asset_host(asset_host) previous, ApplicationController.asset_host = ApplicationController.asset_host, asset_host Rails.application.importmap.send(:clear_cache)