secure_headers 3.6.4 → 3.6.5

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of secure_headers might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fec7efedf547e7aff5f7193f3306802367df524e
4
- data.tar.gz: 5d4a99a2f5989e2c119b6d8be2ed232850635855
3
+ metadata.gz: 17b1294265412b033c265b34e05ce2e4b2655d58
4
+ data.tar.gz: 2febd47d96fa32beb7b662e7c990f8ac5f3c3f64
5
5
  SHA512:
6
- metadata.gz: d5ca176a980b3acf9d97442d13e6109c5a8e8043f796733b3ffbee16f45554acd1f46ee2874fd3099be4f9217618b1591e75ec1ac6c7bc7e2e49acce3e06dbcf
7
- data.tar.gz: 9881f2a604975c4d1f64b4cbc690c063751b8f573f0db87a5c2593326fa5ffcdb83e533d95d9a1ce46551d97192c7faa48e6a5f9485765252d25f53b66d168f1
6
+ metadata.gz: cccc0f3501e0ceaa5ce9bed046952d0469c06f74201afbca405686508ec87ca93fbd301018a1134227827af1069b738b6849cc3415cd115810014894fff42e46
7
+ data.tar.gz: 1e22a0849cfbbe6a24eb3de3026b2b3a0c4c581d0a825abd6d31fcb23df591ff74f563c82101a787596f650b5dd6be4994a1fc3b8ab8a946e2c166f74b86cd85
data/.rspec CHANGED
@@ -1 +1,2 @@
1
1
  --order rand
2
+ --warnings
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 3.6.5
2
+
3
+ Update clear-site-data header to use current format specified by the specification.
4
+
1
5
  ## 3.6.4
2
6
 
3
7
  Fix case where mixing frame-src/child-src dynamically would behave in unexpected ways: https://github.com/twitter/secureheaders/pull/325
@@ -196,7 +200,7 @@ You can add hash sources directly to your policy :
196
200
  rake secure_headers:generate_hashes
197
201
  ```
198
202
 
199
- This will generate a file (`config/config/secure_headers_generated_hashes.yml` by default, you can override by setting `ENV["secure_headers_generated_hashes_file"]`) containing a mapping of file names with the array of hash values found on that page. When ActionView renders a given file, we check if there are any known hashes for that given file. If so, they are added as values to the header.
203
+ This will generate a file (`config/secure_headers_generated_hashes.yml` by default, you can override by setting `ENV["secure_headers_generated_hashes_file"]`) containing a mapping of file names with the array of hash values found on that page. When ActionView renders a given file, we check if there are any known hashes for that given file. If so, they are added as values to the header.
200
204
 
201
205
  ```yaml
202
206
  ---
data/CONTRIBUTING.md CHANGED
@@ -15,7 +15,7 @@ Please note that this project is released with a [Contributor Code of Conduct][c
15
15
  0. Configure and install the dependencies: `bundle install`
16
16
  0. Make sure the tests pass on your machine: `bundle exec rspec spec`
17
17
  0. Create a new branch: `git checkout -b my-branch-name`
18
- 0. Make your change, add tests, and make sure the tests still pass
18
+ 0. Make your change, add tests, and make sure the tests still pass and that no warnings are raised
19
19
  0. Push to your fork and [submit a pull request][pr]
20
20
  0. Pat your self on the back and wait for your pull request to be reviewed and merged.
21
21
 
@@ -25,7 +25,7 @@ Here are a few things you can do that will increase the likelihood of your pull
25
25
  - Keep your change as focused as possible. If there are multiple changes you would like to make that are not dependent upon each other, consider submitting them as separate pull requests.
26
26
  - Write a [good commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
27
27
 
28
- ## Releasing
28
+ ## Releasing
29
29
 
30
30
  0. Ensure CI is green
31
31
  0. Pull the latest code
@@ -39,5 +39,3 @@ Here are a few things you can do that will increase the likelihood of your pull
39
39
 
40
40
  - [How to Contribute to Open Source](https://opensource.guide/how-to-contribute/)
41
41
  - [Using Pull Requests](https://help.github.com/articles/about-pull-requests/)
42
-
43
-
data/README.md CHANGED
@@ -18,7 +18,7 @@ The gem will automatically apply several headers that are related to security.
18
18
  - X-Permitted-Cross-Domain-Policies - [Restrict Adobe Flash Player's access to data](https://www.adobe.com/devnet/adobe-media-server/articles/cross-domain-xml-for-streaming.html)
19
19
  - Referrer-Policy - [Referrer Policy draft](https://w3c.github.io/webappsec-referrer-policy/)
20
20
  - Public Key Pinning - Pin certificate fingerprints in the browser to prevent man-in-the-middle attacks due to compromised Certificate Authorities. [Public Key Pinning Specification](https://tools.ietf.org/html/rfc7469)
21
- - Clear-Site-Data - Clearing browser data for origin. [Clear-Site-Data specification](https://www.w3.org/TR/clear-site-data/).
21
+ - Clear-Site-Data - Clearing browser data for origin. [Clear-Site-Data specification](https://w3c.github.io/webappsec-clear-site-data/).
22
22
 
23
23
  It can also mark all http cookies with the Secure, HttpOnly and SameSite attributes (when configured to do so).
24
24
 
data/docs/hashes.md CHANGED
@@ -21,7 +21,7 @@ You can add hash sources directly to your policy :
21
21
  rake secure_headers:generate_hashes
22
22
  ```
23
23
 
24
- This will generate a file (`config/config/secure_headers_generated_hashes.yml` by default, you can override by setting `ENV["secure_headers_generated_hashes_file"]`) containing a mapping of file names with the array of hash values found on that page. When ActionView renders a given file, we check if there are any known hashes for that given file. If so, they are added as values to the header.
24
+ This will generate a file (`config/secure_headers_generated_hashes.yml` by default, you can override by setting `ENV["secure_headers_generated_hashes_file"]`) containing a mapping of file names with the array of hash values found on that page. When ActionView renders a given file, we check if there are any known hashes for that given file. If so, they are added as values to the header.
25
25
 
26
26
  ```yaml
27
27
  ---
@@ -163,7 +163,8 @@ module SecureHeaders
163
163
  # returned is meant to be merged into the header value from `@app.call(env)`
164
164
  # in Rack middleware.
165
165
  def header_hash_for(request)
166
- config = config_for(request, prevent_dup = true)
166
+ prevent_dup = true
167
+ config = config_for(request, prevent_dup)
167
168
  headers = config.cached_headers
168
169
  user_agent = UserAgent.parse(request.user_agent)
169
170
 
@@ -31,7 +31,7 @@ module SecureHeaders
31
31
  raise NotYetConfiguredError, "#{base} policy not yet supplied"
32
32
  end
33
33
  override = @configurations[base].dup
34
- override.instance_eval &block if block_given?
34
+ override.instance_eval(&block) if block_given?
35
35
  add_configuration(name, override)
36
36
  end
37
37
 
@@ -120,19 +120,36 @@ module SecureHeaders
120
120
 
121
121
  attr_reader :cached_headers, :csp, :cookies, :csp_report_only, :hpkp, :hpkp_report_host
122
122
 
123
+ @script_hashes = nil
124
+ @style_hashes = nil
125
+
123
126
  HASH_CONFIG_FILE = ENV["secure_headers_generated_hashes_file"] || "config/secure_headers_generated_hashes.yml"
124
- if File.exists?(HASH_CONFIG_FILE)
127
+ if File.exist?(HASH_CONFIG_FILE)
125
128
  config = YAML.safe_load(File.open(HASH_CONFIG_FILE))
126
129
  @script_hashes = config["scripts"]
127
130
  @style_hashes = config["styles"]
128
131
  end
129
132
 
130
133
  def initialize(&block)
134
+ @cookies = nil
135
+ @clear_site_data = nil
136
+ @csp = nil
137
+ @csp_report_only = nil
138
+ @hpkp_report_host = nil
139
+ @hpkp = nil
140
+ @hsts = nil
141
+ @x_content_type_options = nil
142
+ @x_download_options = nil
143
+ @x_frame_options = nil
144
+ @x_permitted_cross_domain_policies = nil
145
+ @x_xss_protection = nil
146
+
131
147
  self.hpkp = OPT_OUT
132
148
  self.referrer_policy = OPT_OUT
133
149
  self.csp = ContentSecurityPolicyConfig.new(ContentSecurityPolicyConfig::DEFAULT)
134
150
  self.csp_report_only = OPT_OUT
135
- instance_eval &block if block_given?
151
+
152
+ instance_eval(&block) if block_given?
136
153
  end
137
154
 
138
155
  # Public: copy everything but the cached headers
@@ -2,7 +2,6 @@ module SecureHeaders
2
2
  class ClearSiteDataConfigError < StandardError; end
3
3
  class ClearSiteData
4
4
  HEADER_NAME = "Clear-Site-Data".freeze
5
- TYPES = "types".freeze
6
5
 
7
6
  # Valid `types`
8
7
  CACHE = "cache".freeze
@@ -22,9 +21,9 @@ module SecureHeaders
22
21
  when nil, OPT_OUT, []
23
22
  # noop
24
23
  when Array
25
- [HEADER_NAME, JSON.dump(TYPES => config)]
24
+ [HEADER_NAME, make_header_value(config)]
26
25
  when true
27
- [HEADER_NAME, JSON.dump(TYPES => ALL_TYPES)]
26
+ [HEADER_NAME, make_header_value(ALL_TYPES)]
28
27
  end
29
28
  end
30
29
 
@@ -36,16 +35,20 @@ module SecureHeaders
36
35
  unless config.all? { |t| t.is_a?(String) }
37
36
  raise ClearSiteDataConfigError.new("types must be Strings")
38
37
  end
39
-
40
- begin
41
- JSON.dump(config)
42
- rescue JSON::GeneratorError, Encoding::UndefinedConversionError
43
- raise ClearSiteDataConfigError.new("types must serializable by JSON")
44
- end
45
38
  else
46
39
  raise ClearSiteDataConfigError.new("config must be an Array of Strings or `true`")
47
40
  end
48
41
  end
42
+
43
+ # Public: Transform a Clear-Site-Data config (an Array of Strings) into a
44
+ # String that can be used as the value for the Clear-Site-Data header.
45
+ #
46
+ # types - An Array of String of types of data to clear.
47
+ #
48
+ # Returns a String of quoted values that are comma separated.
49
+ def make_header_value(types)
50
+ types.map { |t| "\"#{t}\""}.join(", ")
51
+ end
49
52
  end
50
53
  end
51
54
  end
@@ -15,6 +15,31 @@ module SecureHeaders
15
15
  end
16
16
 
17
17
  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
+ @object_src = nil
31
+ @plugin_types = nil
32
+ @preserve_schemes = nil
33
+ @reflected_xss = nil
34
+ @report_only = nil
35
+ @report_uri = nil
36
+ @sandbox = nil
37
+ @script_nonce = nil
38
+ @script_src = nil
39
+ @style_nonce = nil
40
+ @style_src = nil
41
+ @upgrade_insecure_requests = nil
42
+
18
43
  from_hash(hash)
19
44
  @modified = false
20
45
  end
@@ -348,9 +348,9 @@ module SecureHeaders
348
348
  end
349
349
 
350
350
  def ensure_valid_sources!(directive, source_expression)
351
- source_expression.each do |source_expression|
352
- if ContentSecurityPolicy::DEPRECATED_SOURCE_VALUES.include?(source_expression)
353
- raise ContentSecurityPolicyConfigError.new("#{directive} contains an invalid keyword source (#{source_expression}). This value must be single quoted.")
351
+ source_expression.each do |expression|
352
+ if ContentSecurityPolicy::DEPRECATED_SOURCE_VALUES.include?(expression)
353
+ raise ContentSecurityPolicyConfigError.new("#{directive} contains an invalid keyword source (#{expression}). This value must be single quoted.")
354
354
  end
355
355
  end
356
356
  end
@@ -49,7 +49,7 @@ module SecureHeaders
49
49
  end
50
50
 
51
51
  def value
52
- header_value = [
52
+ [
53
53
  max_age_directive,
54
54
  pin_directives,
55
55
  report_uri_directive,
@@ -95,9 +95,9 @@ module SecureHeaders
95
95
  <<-EOF
96
96
  \n\n*** WARNING: Unrecognized hash in #{file_path}!!! Value: #{hash_value} ***
97
97
  #{content}
98
- *** Run #{SECURE_HEADERS_RAKE_TASK} or add the following to config/script_hashes.yml:***
98
+ *** Run #{SECURE_HEADERS_RAKE_TASK} or add the following to config/secure_headers_generated_hashes.yml:***
99
99
  #{file_path}:
100
- - #{hash_value}\n\n
100
+ - \"#{hash_value}\"\n\n
101
101
  NOTE: dynamic javascript is not supported using script hash integration
102
102
  on purpose. It defeats the point of using it in the first place.
103
103
  EOF
@@ -1,7 +1,7 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  Gem::Specification.new do |gem|
3
3
  gem.name = "secure_headers"
4
- gem.version = "3.6.4"
4
+ gem.version = "3.6.5"
5
5
  gem.authors = ["Neil Matatall"]
6
6
  gem.email = ["neil.matatall@gmail.com"]
7
7
  gem.description = 'Manages application of security headers with many safe defaults.'
@@ -19,30 +19,16 @@ module SecureHeaders
19
19
  name, value = described_class.make_header(true)
20
20
 
21
21
  expect(name).to eq(ClearSiteData::HEADER_NAME)
22
- expect(value).to eq(normalize_json(<<-HERE))
23
- {
24
- "types": [
25
- "cache",
26
- "cookies",
27
- "storage",
28
- "executionContexts"
29
- ]
30
- }
31
- HERE
22
+ expect(value).to eq(
23
+ %("cache", "cookies", "storage", "executionContexts")
24
+ )
32
25
  end
33
26
 
34
27
  it "returns specified types" do
35
28
  name, value = described_class.make_header(["foo", "bar"])
36
29
 
37
30
  expect(name).to eq(ClearSiteData::HEADER_NAME)
38
- expect(value).to eq(normalize_json(<<-HERE))
39
- {
40
- "types": [
41
- "foo",
42
- "bar"
43
- ]
44
- }
45
- HERE
31
+ expect(value).to eq(%("foo", "bar"))
46
32
  end
47
33
  end
48
34
 
@@ -83,12 +69,6 @@ module SecureHeaders
83
69
  end.to raise_error(ClearSiteDataConfigError)
84
70
  end
85
71
 
86
- it "fails for non-serializable config" do
87
- expect do
88
- described_class.validate_config!(["hi \255"])
89
- end.to raise_error(ClearSiteDataConfigError)
90
- end
91
-
92
72
  it "fails for other types of config" do
93
73
  expect do
94
74
  described_class.validate_config!(:cookies)
@@ -96,8 +76,11 @@ module SecureHeaders
96
76
  end
97
77
  end
98
78
 
99
- def normalize_json(json)
100
- JSON.dump(JSON.parse(json))
79
+ describe "make_header_value" do
80
+ it "returns a string of quoted values that are comma separated" do
81
+ value = described_class.make_header_value(["foo", "bar"])
82
+ expect(value).to eq(%("foo", "bar"))
83
+ end
101
84
  end
102
85
  end
103
86
  end
@@ -37,7 +37,6 @@ class Message < ERB
37
37
  background-color: black;
38
38
  }
39
39
  </style>
40
- <%= @name %>
41
40
 
42
41
  TEMPLATE
43
42
  end
@@ -105,7 +105,7 @@ module SecureHeaders
105
105
  end
106
106
 
107
107
  it "produces a UA-specific CSP when overriding (and busting the cache)" do
108
- config = Configuration.default do |config|
108
+ Configuration.default do |config|
109
109
  config.csp = {
110
110
  default_src: %w('self'),
111
111
  child_src: %w('self')
@@ -231,7 +231,7 @@ module SecureHeaders
231
231
 
232
232
  SecureHeaders.content_security_policy_script_nonce(request) # should add the value to the header
233
233
  hash = SecureHeaders.header_hash_for(chrome_request)
234
- expect(hash[ContentSecurityPolicyConfig::HEADER_NAME]).to match /\Adefault-src 'self'; script-src 'self' 'nonce-.*'\z/
234
+ expect(hash[ContentSecurityPolicyConfig::HEADER_NAME]).to match(/\Adefault-src 'self'; script-src 'self' 'nonce-.*'\z/)
235
235
  end
236
236
 
237
237
  it "appends a hash to a missing script-src value" do
@@ -243,7 +243,7 @@ module SecureHeaders
243
243
 
244
244
  SecureHeaders.append_content_security_policy_directives(request, script_src: %w('sha256-abc123'))
245
245
  hash = SecureHeaders.header_hash_for(chrome_request)
246
- expect(hash[ContentSecurityPolicyConfig::HEADER_NAME]).to match /\Adefault-src 'self'; script-src 'self' 'sha256-abc123'\z/
246
+ expect(hash[ContentSecurityPolicyConfig::HEADER_NAME]).to match(/\Adefault-src 'self'; script-src 'self' 'sha256-abc123'\z/)
247
247
  end
248
248
 
249
249
  it "overrides individual directives" do
@@ -279,7 +279,7 @@ module SecureHeaders
279
279
  end
280
280
 
281
281
  safari_request = Rack::Request.new(request.env.merge("HTTP_USER_AGENT" => USER_AGENTS[:safari5]))
282
- nonce = SecureHeaders.content_security_policy_script_nonce(safari_request)
282
+ SecureHeaders.content_security_policy_script_nonce(safari_request)
283
283
  hash = SecureHeaders.header_hash_for(safari_request)
284
284
  expect(hash[ContentSecurityPolicyConfig::HEADER_NAME]).to eq("default-src 'self'; script-src mycdn.com 'unsafe-inline'; style-src 'self'")
285
285
  end
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: 3.6.4
4
+ version: 3.6.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Neil Matatall
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-05-03 00:00:00.000000000 Z
11
+ date: 2017-06-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake