secure_headers 6.5.0 → 6.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bafd5e6390db0f1975599ab34f1293986a5c0a1ced14f6cfeca47fd114ce87d4
4
- data.tar.gz: 177dc27fa8238fe1a8baa238f6baa244b2c03393f61269e9b417e5ea3a4a4bba
3
+ metadata.gz: 6919954e57f87c70a4fa42baa5285649bd7484ec6785894a2b461b6f52558f29
4
+ data.tar.gz: 710492a0e64a47f41f2b079e6d4799922aa05e51d017cacafcc20d77383815ee
5
5
  SHA512:
6
- metadata.gz: 7a24f853958892e2780dec3cfd8f631d394c959cda6d3f8be5d701792fc1ce57d4141ca88e7b0980fcac979cc855a0c5bc9165a05b314fe281ce092a438f1fe1
7
- data.tar.gz: c082a3ee192452712f8e9c7ed18d5c21b5b3eb1712c3d9a4df44220093cf1be09a8e5384f5c8a8909820f1e0048c6d3b6915cc29081288bcf13361bf8cf7dbed
6
+ metadata.gz: efd8e608dfeafc5d7e7fcd06274b0b8ed0c640744ab9d8113597bef916f31666cbf518b1dcd6869d7af42fbcbaf15a6a4cf8100b97fcbf52f5ba790e495e26c0
7
+ data.tar.gz: dcc504641e1c22b24a05c76534e2f8ba7a7fd5ff1b5f891eb467d23876c60900ef235d2dd4ba49af4352b23ffd1cd246c720aff79668244b6a10cec3aab8ed6f
@@ -0,0 +1,6 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "github-actions"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
@@ -7,10 +7,10 @@ jobs:
7
7
  runs-on: ubuntu-latest
8
8
  strategy:
9
9
  matrix:
10
- ruby: [ '2.6', '2.7', '3.0', '3.1' ]
10
+ ruby: [ '2.6', '2.7', '3.0', '3.1', '3.2' ]
11
11
 
12
12
  steps:
13
- - uses: actions/checkout@v2
13
+ - uses: actions/checkout@v3
14
14
  - name: Set up Ruby ${{ matrix.ruby }}
15
15
  uses: ruby/setup-ruby@v1
16
16
  with:
data/Gemfile CHANGED
@@ -3,6 +3,8 @@ source "https://rubygems.org"
3
3
 
4
4
  gemspec
5
5
 
6
+ gem "benchmark-ips"
7
+
6
8
  group :test do
7
9
  gem "coveralls"
8
10
  gem "json"
data/README.md CHANGED
@@ -62,7 +62,6 @@ SecureHeaders::Configuration.default do |config|
62
62
  # directive values: these values will directly translate into source directives
63
63
  default_src: %w('none'),
64
64
  base_uri: %w('self'),
65
- block_all_mixed_content: true, # see https://www.w3.org/TR/mixed-content/
66
65
  child_src: %w('self'), # if child-src isn't supported, the value for frame-src will be set.
67
66
  connect_src: %w(wss:),
68
67
  font_src: %w('self' data:),
@@ -92,6 +91,9 @@ SecureHeaders::Configuration.default do |config|
92
91
  end
93
92
  ```
94
93
 
94
+ ### Deprecated Configuration Values
95
+ * `block_all_mixed_content` - this value is deprecated in favor of `upgrade_insecure_requests`. See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/block-all-mixed-content for more information.
96
+
95
97
  ## Default values
96
98
 
97
99
  All headers except for PublicKeyPins and ClearSiteData have a default value. The default set of headers is:
@@ -83,14 +83,17 @@ module SecureHeaders
83
83
  # can lead to modifying parent objects.
84
84
  def deep_copy(config)
85
85
  return unless config
86
- config.each_with_object({}) do |(key, value), hash|
87
- hash[key] =
88
- if value.is_a?(Array)
86
+ result = {}
87
+ config.each_pair do |key, value|
88
+ result[key] =
89
+ case value
90
+ when Array
89
91
  value.dup
90
92
  else
91
93
  value
92
94
  end
93
95
  end
96
+ result
94
97
  end
95
98
 
96
99
  # Private: Returns the internal default configuration. This should only
@@ -20,9 +20,9 @@ module SecureHeaders
20
20
  config
21
21
  end
22
22
 
23
- @preserve_schemes = @config.preserve_schemes
24
- @script_nonce = @config.script_nonce
25
- @style_nonce = @config.style_nonce
23
+ @preserve_schemes = @config[:preserve_schemes]
24
+ @script_nonce = @config[:script_nonce]
25
+ @style_nonce = @config[:style_nonce]
26
26
  end
27
27
 
28
28
  ##
@@ -1,66 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
  module SecureHeaders
3
3
  module DynamicConfig
4
- def self.included(base)
5
- base.send(:attr_reader, *base.attrs)
6
- base.attrs.each do |attr|
7
- base.send(:define_method, "#{attr}=") do |value|
8
- if self.class.attrs.include?(attr)
9
- write_attribute(attr, value)
10
- else
11
- raise ContentSecurityPolicyConfigError, "Unknown config directive: #{attr}=#{value}"
12
- end
13
- end
14
- end
15
- end
16
-
17
4
  def initialize(hash)
18
- @base_uri = nil
19
- @block_all_mixed_content = nil
20
- @child_src = nil
21
- @connect_src = nil
22
- @default_src = nil
23
- @font_src = nil
24
- @form_action = nil
25
- @frame_ancestors = nil
26
- @frame_src = nil
27
- @img_src = nil
28
- @manifest_src = nil
29
- @media_src = nil
30
- @navigate_to = nil
31
- @object_src = nil
32
- @plugin_types = nil
33
- @prefetch_src = nil
34
- @preserve_schemes = nil
35
- @report_only = nil
36
- @report_uri = nil
37
- @require_sri_for = nil
38
- @require_trusted_types_for = nil
39
- @sandbox = nil
40
- @script_nonce = nil
41
- @script_src = nil
42
- @script_src_elem = nil
43
- @script_src_attr = nil
44
- @style_nonce = nil
45
- @style_src = nil
46
- @style_src_elem = nil
47
- @style_src_attr = nil
48
- @trusted_types = nil
49
- @worker_src = nil
50
- @upgrade_insecure_requests = nil
51
- @disable_nonce_backwards_compatibility = nil
5
+ @config = {}
52
6
 
53
7
  from_hash(hash)
54
8
  end
55
9
 
10
+ def initialize_copy(hash)
11
+ @config = hash.to_h
12
+ end
13
+
56
14
  def update_directive(directive, value)
57
- self.send("#{directive}=", value)
15
+ @config[directive] = value
58
16
  end
59
17
 
60
18
  def directive_value(directive)
61
- if self.class.attrs.include?(directive)
62
- self.send(directive)
63
- end
19
+ # No need to check attrs, as we only assign valid keys
20
+ @config[directive]
64
21
  end
65
22
 
66
23
  def merge(new_hash)
@@ -78,10 +35,7 @@ module SecureHeaders
78
35
  end
79
36
 
80
37
  def to_h
81
- self.class.attrs.each_with_object({}) do |key, hash|
82
- value = self.send(key)
83
- hash[key] = value unless value.nil?
84
- end
38
+ @config.dup
85
39
  end
86
40
 
87
41
  def dup
@@ -114,8 +68,11 @@ module SecureHeaders
114
68
 
115
69
  def write_attribute(attr, value)
116
70
  value = value.dup if PolicyManagement::DIRECTIVE_VALUE_TYPES[attr] == :source_list
117
- attr_variable = "@#{attr}"
118
- self.instance_variable_set(attr_variable, value)
71
+ if value.nil?
72
+ @config.delete(attr)
73
+ else
74
+ @config[attr] = value
75
+ end
119
76
  end
120
77
  end
121
78
 
@@ -123,7 +80,7 @@ module SecureHeaders
123
80
  class ContentSecurityPolicyConfig
124
81
  HEADER_NAME = "Content-Security-Policy".freeze
125
82
 
126
- ATTRS = PolicyManagement::ALL_DIRECTIVES + PolicyManagement::META_CONFIGS + PolicyManagement::NONCES
83
+ ATTRS = Set.new(PolicyManagement::ALL_DIRECTIVES + PolicyManagement::META_CONFIGS + PolicyManagement::NONCES)
127
84
  def self.attrs
128
85
  ATTRS
129
86
  end
@@ -80,9 +80,9 @@ module SecureHeaders
80
80
  end
81
81
 
82
82
  def conditionally_flag?(configuration)
83
- if(Array(configuration[:only]).any? && (Array(configuration[:only]) & parsed_cookie.keys).any?)
83
+ if (Array(configuration[:only]).any? && (Array(configuration[:only]) & parsed_cookie.keys).any?)
84
84
  true
85
- elsif(Array(configuration[:except]).any? && (Array(configuration[:except]) & parsed_cookie.keys).none?)
85
+ elsif (Array(configuration[:except]).any? && (Array(configuration[:except]) & parsed_cookie.keys).none?)
86
86
  true
87
87
  else
88
88
  false
@@ -71,7 +71,6 @@ module SecureHeaders
71
71
 
72
72
  # All the directives currently under consideration for CSP level 3.
73
73
  # https://w3c.github.io/webappsec/specs/CSP2/
74
- BLOCK_ALL_MIXED_CONTENT = :block_all_mixed_content
75
74
  MANIFEST_SRC = :manifest_src
76
75
  NAVIGATE_TO = :navigate_to
77
76
  PREFETCH_SRC = :prefetch_src
@@ -85,7 +84,6 @@ module SecureHeaders
85
84
 
86
85
  DIRECTIVES_3_0 = [
87
86
  DIRECTIVES_2_0,
88
- BLOCK_ALL_MIXED_CONTENT,
89
87
  MANIFEST_SRC,
90
88
  NAVIGATE_TO,
91
89
  PREFETCH_SRC,
@@ -118,7 +116,6 @@ module SecureHeaders
118
116
 
119
117
  DIRECTIVE_VALUE_TYPES = {
120
118
  BASE_URI => :source_list,
121
- BLOCK_ALL_MIXED_CONTENT => :boolean,
122
119
  CHILD_SRC => :source_list,
123
120
  CONNECT_SRC => :source_list,
124
121
  DEFAULT_SRC => :source_list,
@@ -241,7 +238,7 @@ module SecureHeaders
241
238
  #
242
239
  # raises an error if the original config is OPT_OUT
243
240
  #
244
- # 1. for non-source-list values (report_only, block_all_mixed_content, upgrade_insecure_requests),
241
+ # 1. for non-source-list values (report_only, upgrade_insecure_requests),
245
242
  # additions will overwrite the original value.
246
243
  # 2. if a value in additions does not exist in the original config, the
247
244
  # default-src value is included to match original behavior.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SecureHeaders
4
- VERSION = "6.5.0"
4
+ VERSION = "6.7.0"
5
5
  end
@@ -92,13 +92,13 @@ module SecureHeaders
92
92
  end
93
93
 
94
94
  it "does add a boolean directive if the value is true" do
95
- csp = ContentSecurityPolicy.new(default_src: ["https://example.org"], block_all_mixed_content: true, upgrade_insecure_requests: true)
96
- expect(csp.value).to eq("default-src example.org; block-all-mixed-content; upgrade-insecure-requests")
95
+ csp = ContentSecurityPolicy.new(default_src: ["https://example.org"], upgrade_insecure_requests: true)
96
+ expect(csp.value).to eq("default-src example.org; upgrade-insecure-requests")
97
97
  end
98
98
 
99
99
  it "does not add a boolean directive if the value is false" do
100
- csp = ContentSecurityPolicy.new(default_src: ["https://example.org"], block_all_mixed_content: true, upgrade_insecure_requests: false)
101
- expect(csp.value).to eq("default-src example.org; block-all-mixed-content")
100
+ csp = ContentSecurityPolicy.new(default_src: ["https://example.org"], upgrade_insecure_requests: false)
101
+ expect(csp.value).to eq("default-src example.org")
102
102
  end
103
103
 
104
104
  it "handles wildcard subdomain with wildcard port" do
@@ -30,7 +30,6 @@ module SecureHeaders
30
30
  default_src: %w(https: 'self'),
31
31
 
32
32
  base_uri: %w('self'),
33
- block_all_mixed_content: true, # see [http://www.w3.org/TR/mixed-content/](http://www.w3.org/TR/mixed-content/)
34
33
  connect_src: %w(wss:),
35
34
  child_src: %w('self' *.twimg.com itunes.apple.com),
36
35
  font_src: %w('self' data:),
@@ -92,12 +91,6 @@ module SecureHeaders
92
91
  end.to raise_error(ContentSecurityPolicyConfigError)
93
92
  end
94
93
 
95
- it "requires :block_all_mixed_content to be a boolean value" do
96
- expect do
97
- ContentSecurityPolicy.validate_config!(ContentSecurityPolicyConfig.new(default_opts.merge(block_all_mixed_content: "steve")))
98
- end.to raise_error(ContentSecurityPolicyConfigError)
99
- end
100
-
101
94
  it "requires :upgrade_insecure_requests to be a boolean value" do
102
95
  expect do
103
96
  ContentSecurityPolicy.validate_config!(ContentSecurityPolicyConfig.new(default_opts.merge(upgrade_insecure_requests: "steve")))
@@ -244,18 +237,18 @@ module SecureHeaders
244
237
  expect(csp.name).to eq(ContentSecurityPolicyReportOnlyConfig::HEADER_NAME)
245
238
  end
246
239
 
247
- it "overrides the :block_all_mixed_content flag" do
240
+ it "overrides the :upgrade_insecure_requests flag" do
248
241
  Configuration.default do |config|
249
242
  config.csp = {
250
243
  default_src: %w(https:),
251
244
  script_src: %w('self'),
252
- block_all_mixed_content: false
245
+ upgrade_insecure_requests: false
253
246
  }
254
247
  end
255
248
  default_policy = Configuration.dup
256
- combined_config = ContentSecurityPolicy.combine_policies(default_policy.csp.to_h, block_all_mixed_content: true)
249
+ combined_config = ContentSecurityPolicy.combine_policies(default_policy.csp.to_h, upgrade_insecure_requests: true)
257
250
  csp = ContentSecurityPolicy.new(combined_config)
258
- expect(csp.value).to eq("default-src https:; block-all-mixed-content; script-src 'self'")
251
+ expect(csp.value).to eq("default-src https:; script-src 'self'; upgrade-insecure-requests")
259
252
  end
260
253
 
261
254
  it "raises an error if appending to a OPT_OUT policy" do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: secure_headers
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.5.0
4
+ version: 6.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Neil Matatall
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-10-25 00:00:00.000000000 Z
11
+ date: 2024-08-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -36,6 +36,7 @@ extra_rdoc_files: []
36
36
  files:
37
37
  - ".github/ISSUE_TEMPLATE.md"
38
38
  - ".github/PULL_REQUEST_TEMPLATE.md"
39
+ - ".github/dependabot.yml"
39
40
  - ".github/workflows/build.yml"
40
41
  - ".github/workflows/github-release.yml"
41
42
  - ".gitignore"
@@ -104,7 +105,7 @@ homepage: https://github.com/twitter/secureheaders
104
105
  licenses:
105
106
  - MIT
106
107
  metadata: {}
107
- post_install_message:
108
+ post_install_message:
108
109
  rdoc_options: []
109
110
  require_paths:
110
111
  - lib
@@ -119,8 +120,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
119
120
  - !ruby/object:Gem::Version
120
121
  version: '0'
121
122
  requirements: []
122
- rubygems_version: 3.3.7
123
- signing_key:
123
+ rubygems_version: 3.0.3.1
124
+ signing_key:
124
125
  specification_version: 4
125
126
  summary: Manages application of security headers with many safe defaults.
126
127
  test_files: