secure_headers 6.5.0 → 6.7.0

Sign up to get free protection for your applications and to get access to all the features.
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: