From 66c2b26db535f0bdc20ba5745ca2deb908bf3171 Mon Sep 17 00:00:00 2001 From: Neil Matatall Date: Mon, 17 Aug 2015 14:43:57 -0700 Subject: [PATCH 1/4] add json export --- lib/secure_headers/headers/content_security_policy.rb | 6 ++++++ .../secure_headers/headers/content_security_policy_spec.rb | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/lib/secure_headers/headers/content_security_policy.rb b/lib/secure_headers/headers/content_security_policy.rb index 3fe73eac..65fe9229 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,11 @@ def value end end + def to_json + build_value + @config.to_json + 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..d1d33c67 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,12 @@ 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 + 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'])) From 8a677df4a5a9dbdb4bbf403ae26bf7e8a9fc2a7f Mon Sep 17 00:00:00 2001 From: Neil Matatall Date: Mon, 17 Aug 2015 15:24:58 -0700 Subject: [PATCH 2/4] add ability to import a policy from json --- .../headers/content_security_policy.rb | 12 +++++++++++- .../headers/content_security_policy_spec.rb | 12 +++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/lib/secure_headers/headers/content_security_policy.rb b/lib/secure_headers/headers/content_security_policy.rb index 65fe9229..b7604fdb 100644 --- a/lib/secure_headers/headers/content_security_policy.rb +++ b/lib/secure_headers/headers/content_security_policy.rb @@ -169,7 +169,17 @@ def value def to_json build_value - @config.to_json + @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 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 d1d33c67..39f0b5a9 100644 --- a/spec/lib/secure_headers/headers/content_security_policy_spec.rb +++ b/spec/lib/secure_headers/headers/content_security_policy_spec.rb @@ -58,7 +58,17 @@ def request_for user_agent, request_uri=nil, options={:ssl => false} 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:"]}) + 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'","https:","about:"],"img-src":["https:","data:"]}) + config = ContentSecurityPolicy.from_json(json1, json2) + 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 From de5add4a9e0bb19dc81e81dd474f557b742e1f0a Mon Sep 17 00:00:00 2001 From: Neil Matatall Date: Mon, 17 Aug 2015 15:30:47 -0700 Subject: [PATCH 3/4] disable 1.8.7 travis jobs (temporarily) --- .travis.yml | 1 - 1 file changed, 1 deletion(-) 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 From 8a77f4783f739954e1e1c5aa4de9ae39a17c85df Mon Sep 17 00:00:00 2001 From: Neil Matatall Date: Mon, 17 Aug 2015 15:39:55 -0700 Subject: [PATCH 4/4] make test demonstrate combining policies --- .../secure_headers/headers/content_security_policy_spec.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 39f0b5a9..fc9ff4b6 100644 --- a/spec/lib/secure_headers/headers/content_security_policy_spec.rb +++ b/spec/lib/secure_headers/headers/content_security_policy_spec.rb @@ -64,8 +64,9 @@ def request_for user_agent, request_uri=nil, options={:ssl => false} 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'","https:","about:"],"img-src":["https:","data:"]}) - config = ContentSecurityPolicy.from_json(json1, json2) + 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:"]})