From af92ce6f09ed96fbad8836eae8739b0191b25dd5 Mon Sep 17 00:00:00 2001 From: Lucas Garron Date: Fri, 14 Oct 2022 15:16:25 -0700 Subject: [PATCH 1/3] Add a regression test for a current bug. --- .../secure_headers/headers/content_security_policy_spec.rb | 5 +++++ 1 file changed, 5 insertions(+) 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 56397600..b3e64c92 100644 --- a/spec/lib/secure_headers/headers/content_security_policy_spec.rb +++ b/spec/lib/secure_headers/headers/content_security_policy_spec.rb @@ -101,6 +101,11 @@ module SecureHeaders expect(csp.value).to eq("default-src example.org; block-all-mixed-content") end + it "handles wildcard subdomain with wildcard port" do + csp = ContentSecurityPolicy.new(default_src: %w(https://*.example.org:*)) + expect(csp.value).to eq("default-src *.example.org:*") + end + it "deduplicates any source expressions" do csp = ContentSecurityPolicy.new(default_src: %w(example.org example.org example.org)) expect(csp.value).to eq("default-src example.org") From cdb40e5b851d56b479892b521cd9eb0b1b1a6a83 Mon Sep 17 00:00:00 2001 From: Lucas Garron Date: Wed, 19 Oct 2022 05:20:48 -0700 Subject: [PATCH 2/3] Remove `dedup_source_list` and replace with a "best-effort" `.uniq` call. --- .../headers/content_security_policy.rb | 20 +------------------ 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/lib/secure_headers/headers/content_security_policy.rb b/lib/secure_headers/headers/content_security_policy.rb index 2c9ef501..566004b8 100644 --- a/lib/secure_headers/headers/content_security_policy.rb +++ b/lib/secure_headers/headers/content_security_policy.rb @@ -133,7 +133,7 @@ def minify_source_list(directive, source_list) unless directive == REPORT_URI || @preserve_schemes source_list = strip_source_schemes(source_list) end - dedup_source_list(source_list) + source_list.uniq end end @@ -151,24 +151,6 @@ def reject_all_values_if_none(source_list) end end - # Removes duplicates and sources that already match an existing wild card. - # - # e.g. *.github.com asdf.github.com becomes *.github.com - def dedup_source_list(sources) - sources = sources.uniq - wild_sources = sources.select { |source| source =~ STAR_REGEXP } - - if wild_sources.any? - schemes = sources.map { |source| [source, URI(source).scheme] }.to_h - sources.reject do |source| - !wild_sources.include?(source) && - wild_sources.any? { |pattern| schemes[pattern] == schemes[source] && File.fnmatch(pattern, source) } - end - else - sources - end - end - # Private: append a nonce to the script/style directories if script_nonce # or style_nonce are provided. def populate_nonces(directive, source_list) From cd73b021880bb368317b780ed6ac6d1841462574 Mon Sep 17 00:00:00 2001 From: Lucas Garron Date: Wed, 19 Oct 2022 05:26:41 -0700 Subject: [PATCH 3/3] Update tests. --- .../headers/content_security_policy_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 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 b3e64c92..314b8963 100644 --- a/spec/lib/secure_headers/headers/content_security_policy_spec.rb +++ b/spec/lib/secure_headers/headers/content_security_policy_spec.rb @@ -48,12 +48,12 @@ module SecureHeaders expect(csp.value).to eq("default-src * 'unsafe-inline' 'unsafe-eval' data: blob:") end - it "minifies source expressions based on overlapping wildcards" do + it "does not minify source expressions based on overlapping wildcards" do config = { default_src: %w(a.example.org b.example.org *.example.org https://*.example.org) } csp = ContentSecurityPolicy.new(config) - expect(csp.value).to eq("default-src *.example.org") + expect(csp.value).to eq("default-src a.example.org b.example.org *.example.org") end it "removes http/s schemes from hosts" do @@ -106,8 +106,8 @@ module SecureHeaders expect(csp.value).to eq("default-src *.example.org:*") end - it "deduplicates any source expressions" do - csp = ContentSecurityPolicy.new(default_src: %w(example.org example.org example.org)) + it "deduplicates source expressions that match exactly (after scheme stripping)" do + csp = ContentSecurityPolicy.new(default_src: %w(example.org https://example.org example.org)) expect(csp.value).to eq("default-src example.org") end