secure_headers 0.4.1 → 0.4.2

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.

Potentially problematic release.


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

data/HISTORY.md CHANGED
@@ -1,3 +1,9 @@
1
+ 0.4.3
2
+ ======
3
+
4
+ - Stupid bug where Fixnums couldn't be used for config values
5
+ - Doc updates
6
+
1
7
  0.4.1
2
8
  ======
3
9
 
data/README.md CHANGED
@@ -41,7 +41,7 @@ By default, it will set all of the headers listed in the options section below u
41
41
 
42
42
  Use the standard `skip_before_filter :filter_name, options` mechanism. e.g. `skip_before_filter :set_csp_header, :only => :tinymce_page`
43
43
 
44
- The following methods are going to be called, unles they are provided in a `skip_before_filter` block.
44
+ The following methods are going to be called, unless they are provided in a `skip_before_filter` block.
45
45
 
46
46
  * `:set_csp_header`
47
47
  * `:set_hsts_header`
@@ -53,10 +53,10 @@ The following methods are going to be called, unles they are provided in a `skip
53
53
 
54
54
  This gem makes a few assumptions about how you will use some features. For example:
55
55
 
56
- * It adds 'chrome-extension:' to your CSP directives by default. This helps drastically reduce the amount of reports, but you can also disable this feature by supplying :disable_chrome_extension => true.
57
- * It fills any blank directives with the value in :default_src Getting a default\-src report is pretty useless. This way, you will always know what type of violation occurred. You can disable this feature by supplying :disable_fill_missing => true.
56
+ * It adds 'chrome-extension:' to your CSP directives by default. This helps drastically reduce the amount of reports, but you can also disable this feature by supplying `:disable_chrome_extension => true`.
57
+ * It fills any blank directives with the value in `:default_src` Getting a default\-src report is pretty useless. This way, you will always know what type of violation occurred. You can disable this feature by supplying `:disable_fill_missing => true`.
58
58
  * It copies the connect\-src value to xhr\-src for AJAX requests when using Firefox.
59
- * Firefox does not support cross\-origin CSP reports. If we are using Firefox, AND the value for :report_uri does not satisfy the same\-origin requirements, we will instead forward to an internal endpoint (`FF_CSP_ENDPOINT`). This is also the case if :report_uri only contains a path, which we assume will be cross host. This endpoint will in turn forward the request to the value in :forward_endpoint without restriction. More information can be found in the "Note on Firefox handling of CSP" section.
59
+ * Firefox does not support cross\-origin CSP reports. If we are using Firefox, AND the value for `:report_uri` does not satisfy the same\-origin requirements, we will instead forward to an internal endpoint (`FF_CSP_ENDPOINT`). This is also the case if `:report_uri` only contains a path, which we assume will be cross host. This endpoint will in turn forward the request to the value in `:forward_endpoint` without restriction. More information can be found in the "Note on Firefox handling of CSP" section.
60
60
 
61
61
 
62
62
  ## Configuration
@@ -159,6 +159,16 @@ and [Mozilla CSP specification](https://wiki.mozilla.org/Security/CSP/Specificat
159
159
  :img_src => 'http://mycdn.example.com'
160
160
  }
161
161
  }
162
+
163
+ # script-nonce is an experimental feature of CSP 1.1 available in Chrome. It allows
164
+ # you to whitelist inline script blocks. For more information, see
165
+ # https://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html#script-nonce
166
+ :script_nonce => { 'abc123' }
167
+
168
+ # you can also use lambdas to use dynamically generated nonces
169
+ :script_nonce => lambda { @script_nonce] = 'something' }
170
+ # which can be used to whitelist a script block:
171
+ # script_tag :nonce = @script_nonce { inline_script_call() }
162
172
  }
163
173
  ```
164
174
 
@@ -72,10 +72,10 @@ module SecureHeaders
72
72
  options = self.class.options_for :csp, options
73
73
  return if options == false
74
74
 
75
- header = ContentSecurityPolicy.new(options, :request => request)
75
+ header = ContentSecurityPolicy.new(options, :request => request, :controller => self)
76
76
  set_header(header.name, header.value)
77
77
  if options && options[:experimental] && options[:enforce]
78
- header = ContentSecurityPolicy.new(options, :experimental => true, :request => request)
78
+ header = ContentSecurityPolicy.new(options, :experimental => true, :request => request, :controller => self)
79
79
  set_header(header.name, header.value)
80
80
  end
81
81
  end
@@ -36,6 +36,7 @@ module SecureHeaders
36
36
  # :report used to determine what :ssl_request, :ua, and :request_uri are set to
37
37
  def initialize(config=nil, options={})
38
38
  @experimental = !!options.delete(:experimental)
39
+ @controller = options.delete(:controller)
39
40
  if options[:request]
40
41
  parse_request(options[:request])
41
42
  else
@@ -65,6 +66,7 @@ module SecureHeaders
65
66
  end
66
67
 
67
68
  @report_uri = @config.delete(:report_uri)
69
+ @script_nonce = @config.delete(:script_nonce)
68
70
 
69
71
  normalize_csp_options
70
72
  normalize_reporting_endpoint
@@ -103,7 +105,8 @@ module SecureHeaders
103
105
  header_value = [
104
106
  build_impl_specific_directives,
105
107
  generic_directives(@config),
106
- report_uri_directive
108
+ report_uri_directive,
109
+ script_nonce_directive,
107
110
  ].join
108
111
 
109
112
  #store the value for next time
@@ -208,6 +211,18 @@ module SecureHeaders
208
211
  "report-uri #{@report_uri};"
209
212
  end
210
213
 
214
+ def script_nonce_directive
215
+ return '' if @script_nonce.nil?
216
+ nonce_value = if @script_nonce.is_a?(String)
217
+ @script_nonce
218
+ elsif @controller
219
+ @controller.instance_exec(&@script_nonce)
220
+ else
221
+ @script_nonce.call
222
+ end
223
+ "script-nonce #{nonce_value};"
224
+ end
225
+
211
226
  def generic_directives(config)
212
227
  header_value = ''
213
228
  if config[:img_src]
@@ -29,7 +29,7 @@ module SecureHeaders
29
29
  end
30
30
 
31
31
  max_age = @config.fetch(:max_age, HSTS_MAX_AGE)
32
- value = "max-age=" + max_age
32
+ value = "max-age=" + max_age.to_s
33
33
  value += "; includeSubdomains" if @config[:include_subdomains]
34
34
 
35
35
  value
@@ -1,3 +1,3 @@
1
1
  module SecureHeaders
2
- VERSION = "0.4.1"
2
+ VERSION = "0.4.2"
3
3
  end
@@ -397,6 +397,38 @@ module SecureHeaders
397
397
  end
398
398
  end
399
399
  end
400
+
401
+ context "when supplying a script nonce callback" do
402
+ let(:options) {
403
+ default_opts.merge({
404
+ :script_nonce => "random",
405
+ })
406
+ }
407
+
408
+ it "uses the value in the X-Webkit-CSP" do
409
+ csp = ContentSecurityPolicy.new(options, :request => request_for(CHROME))
410
+ csp.value.should match "script-nonce random;"
411
+ end
412
+
413
+ it "uses the value in the X-Content-Security-Policy" do
414
+ csp = ContentSecurityPolicy.new(options, :request => request_for(FIREFOX))
415
+ csp.value.should match "script-nonce random;"
416
+ end
417
+
418
+ it "runs a dynamic nonce generator" do
419
+ options[:script_nonce] = lambda { 'something' }
420
+ csp = ContentSecurityPolicy.new(options, :request => request_for(CHROME))
421
+ csp.value.should match "script-nonce something;"
422
+ end
423
+
424
+ it "runs against the given controller context" do
425
+ fake_params = {}
426
+ options[:script_nonce] = lambda { params[:script_nonce] = 'something' }
427
+ csp = ContentSecurityPolicy.new(options, :request => request_for(CHROME), :controller => double(:params => fake_params))
428
+ csp.value.should match "script-nonce something;"
429
+ fake_params.should == {:script_nonce => 'something'}
430
+ end
431
+ end
400
432
  end
401
433
  end
402
434
  end
@@ -26,6 +26,12 @@ module SecureHeaders
26
26
  s.value.should == "max-age=#{age}"
27
27
  end
28
28
 
29
+ it "allows you to specify max-age as a Fixnum" do
30
+ age = 8675309
31
+ s = StrictTransportSecurity.new(:max_age => age)
32
+ s.value.should == "max-age=#{age}"
33
+ end
34
+
29
35
  context "with an invalid configuration" do
30
36
  context "with a hash argument" do
31
37
  it "should allow string values for max-age" do
metadata CHANGED
@@ -1,55 +1,62 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: secure_headers
3
- version: !ruby/object:Gem::Version
4
- version: 0.4.1
3
+ version: !ruby/object:Gem::Version
4
+ hash: 11
5
5
  prerelease:
6
+ segments:
7
+ - 0
8
+ - 4
9
+ - 2
10
+ version: 0.4.2
6
11
  platform: ruby
7
- authors:
12
+ authors:
8
13
  - Neil Matatall
9
14
  autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
- date: 2013-04-10 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
17
+
18
+ date: 2013-05-05 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
15
21
  name: brwsr
16
- requirement: !ruby/object:Gem::Requirement
17
- none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
21
- version: 1.1.1
22
- type: :runtime
23
22
  prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
23
+ requirement: &id001 !ruby/object:Gem::Requirement
25
24
  none: false
26
- requirements:
27
- - - ! '>='
28
- - !ruby/object:Gem::Version
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 17
29
+ segments:
30
+ - 1
31
+ - 1
32
+ - 1
29
33
  version: 1.1.1
30
- - !ruby/object:Gem::Dependency
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
31
37
  name: rake
32
- requirement: !ruby/object:Gem::Requirement
33
- none: false
34
- requirements:
35
- - - ! '>='
36
- - !ruby/object:Gem::Version
37
- version: '0'
38
- type: :development
39
38
  prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
39
+ requirement: &id002 !ruby/object:Gem::Requirement
41
40
  none: false
42
- requirements:
43
- - - ! '>='
44
- - !ruby/object:Gem::Version
45
- version: '0'
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ hash: 3
45
+ segments:
46
+ - 0
47
+ version: "0"
48
+ type: :development
49
+ version_requirements: *id002
46
50
  description: Add easily configured browser headers to responses.
47
- email:
51
+ email:
48
52
  - neil.matatall@gmail.com
49
53
  executables: []
54
+
50
55
  extensions: []
56
+
51
57
  extra_rdoc_files: []
52
- files:
58
+
59
+ files:
53
60
  - .gitignore
54
61
  - .rvmrc
55
62
  - .travis.yml
@@ -170,32 +177,39 @@ files:
170
177
  - spec/spec_helper.rb
171
178
  - travis.sh
172
179
  homepage: https://github.com/twitter/secureheaders
173
- licenses:
180
+ licenses:
174
181
  - Apache Public License 2.0
175
182
  post_install_message:
176
183
  rdoc_options: []
177
- require_paths:
184
+
185
+ require_paths:
178
186
  - lib
179
- required_ruby_version: !ruby/object:Gem::Requirement
187
+ required_ruby_version: !ruby/object:Gem::Requirement
180
188
  none: false
181
- requirements:
182
- - - ! '>='
183
- - !ruby/object:Gem::Version
184
- version: '0'
185
- required_rubygems_version: !ruby/object:Gem::Requirement
189
+ requirements:
190
+ - - ">="
191
+ - !ruby/object:Gem::Version
192
+ hash: 3
193
+ segments:
194
+ - 0
195
+ version: "0"
196
+ required_rubygems_version: !ruby/object:Gem::Requirement
186
197
  none: false
187
- requirements:
188
- - - ! '>='
189
- - !ruby/object:Gem::Version
190
- version: '0'
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ hash: 3
202
+ segments:
203
+ - 0
204
+ version: "0"
191
205
  requirements: []
206
+
192
207
  rubyforge_project:
193
208
  rubygems_version: 1.8.24
194
209
  signing_key:
195
210
  specification_version: 3
196
- summary: Add easily configured browser headers to responses including content security
197
- policy, x-frame-options, strict-transport-security and more.
198
- test_files:
211
+ summary: Add easily configured browser headers to responses including content security policy, x-frame-options, strict-transport-security and more.
212
+ test_files:
199
213
  - spec/controllers/content_security_policy_controller_spec.rb
200
214
  - spec/lib/secure_headers/headers/content_security_policy_spec.rb
201
215
  - spec/lib/secure_headers/headers/strict_transport_security_spec.rb