diff --git a/lib/secure_headers/headers/content_security_policy.rb b/lib/secure_headers/headers/content_security_policy.rb index f3b1d918..a3d6e789 100644 --- a/lib/secure_headers/headers/content_security_policy.rb +++ b/lib/secure_headers/headers/content_security_policy.rb @@ -210,6 +210,8 @@ def combine_policies(original, additions) raise ContentSecurityPolicyConfigError.new("Attempted to override an opt-out CSP config.") end + original = original.dup if original.frozen? + # in case we would be appending to an empty directive, fill it with the default-src value additions.keys.each do |directive| unless original[directive] || !source_list?(directive) diff --git a/spec/lib/secure_headers/headers/content_security_policy_spec.rb b/spec/lib/secure_headers/headers/content_security_policy_spec.rb index 300d3b35..3f5990fb 100644 --- a/spec/lib/secure_headers/headers/content_security_policy_spec.rb +++ b/spec/lib/secure_headers/headers/content_security_policy_spec.rb @@ -117,6 +117,17 @@ module SecureHeaders expect(csp.value).to eq("default-src https:; script-src https: anothercdn.com") end + it "combines directives where the original value is nil and the hash is frozen" do + Configuration.default do |config| + config.csp = { + default_src: %w('self'), + report_only: false + }.freeze + end + combined_config = CSP.combine_policies(Configuration.get.csp, report_uri: %w(https://report-uri.io/asdf)) + expect(combined_config[:report_uri]).to_not be_nil + end + it "overrides the report_only flag" do Configuration.default do |config| config.csp = {