diff --git a/.travis.yml b/.travis.yml index 795c10cf..8835a1e8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,6 @@ rvm: - "2.1" - "2.0.0" - "1.9.3" - - "1.8.7" - "jruby-19mode" sudo: false diff --git a/lib/secure_headers/headers/content_security_policy.rb b/lib/secure_headers/headers/content_security_policy.rb index 3fe73eac..b7604fdb 100644 --- a/lib/secure_headers/headers/content_security_policy.rb +++ b/lib/secure_headers/headers/content_security_policy.rb @@ -2,6 +2,7 @@ require 'base64' require 'securerandom' require 'user_agent_parser' +require 'json' module SecureHeaders class ContentSecurityPolicyBuildError < StandardError; end @@ -166,6 +167,21 @@ def value end end + def to_json + build_value + @config.to_json.gsub(/(\w+)_src/, "\\1-src") + end + + def self.from_json(*json_configs) + json_configs.inject({}) do |combined_config, one_config| + one_config = one_config.gsub(/(\w+)-src/, "\\1_src") + config = JSON.parse(one_config, :symbolize_names => true) + combined_config.merge(config) do |_, lhs, rhs| + lhs | rhs + end + end + end + private def add_script_hashes 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 dcc337ca..fc9ff4b6 100644 --- a/spec/lib/secure_headers/headers/content_security_policy_spec.rb +++ b/spec/lib/secure_headers/headers/content_security_policy_spec.rb @@ -56,6 +56,23 @@ def request_for user_agent, request_uri=nil, options={:ssl => false} end end + it "exports a policy to JSON" do + policy = ContentSecurityPolicy.new(default_opts) + expected = %({"default-src":["https:"],"script-src":["'unsafe-inline'","'unsafe-eval'","https:","data:"],"style-src":["'unsafe-inline'","https:","about:"],"img-src":["https:","data:"]}) + expect(policy.to_json).to eq(expected) + end + + it "imports JSON to build a policy" do + json1 = %({"default-src":["https:"],"script-src":["'unsafe-inline'","'unsafe-eval'","https:","data:"]}) + json2 = %({"style-src":["'unsafe-inline'"],"img-src":["https:","data:"]}) + json3 = %({"style-src":["https:","about:"]}) + config = ContentSecurityPolicy.from_json(json1, json2, json3) + policy = ContentSecurityPolicy.new(config.merge(:disable_fill_missing => true)) + + expected = %({"default-src":["https:"],"script-src":["'unsafe-inline'","'unsafe-eval'","https:","data:"],"style-src":["'unsafe-inline'","https:","about:"],"img-src":["https:","data:"]}) + expect(policy.to_json).to eq(expected) + end + context "when using hash sources" do it "adds hashes and unsafe-inline to the script-src" do policy = ContentSecurityPolicy.new(default_opts.merge(:script_hashes => ['sha256-abc123']))