secure_headers 2.0.0 → 2.1.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 +7 -0
- data/.ruby-version +1 -1
- data/README.md +35 -3
- data/lib/secure_headers/headers/content_security_policy.rb +8 -2
- data/lib/secure_headers/headers/public_key_pins.rb +95 -0
- data/lib/secure_headers/version.rb +1 -1
- data/lib/secure_headers/view_helper.rb +1 -1
- data/lib/secure_headers.rb +14 -1
- data/spec/lib/secure_headers/headers/public_key_pins_spec.rb +37 -0
- data/spec/lib/secure_headers_spec.rb +47 -6
- data/spec/spec_helper.rb +1 -0
- metadata +16 -17
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 16e634b2502cd5ee9d87fac9a9d2c6af9bc48fda
|
|
4
|
+
data.tar.gz: 1416e09703db75cdf25379a1273477f346080c72
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: d1483f86c255f59593766bf3312d0085df5b59281c2daf426c16bf930c92c06ae17c17e07984be696b1719336e89ea7000e19948713b310354c749200e2debd6
|
|
7
|
+
data.tar.gz: eaf23b06c98757048b1516d87e429a23b5c70606db476f90eb042250bbd863bd1fddfdbcf12a6fce51e077a0ee3e6332cedcc041514de6a0ce55295d77a4bd65
|
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
2.1.6
|
data/README.md
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
# SecureHeaders [](http://travis-ci.org/twitter/secureheaders) [](https://codeclimate.com/github/twitter/secureheaders) [](https://coveralls.io/r/twitter/secureheaders)
|
|
2
2
|
|
|
3
3
|
The gem will automatically apply several headers that are related to security. This includes:
|
|
4
|
-
- Content Security Policy (CSP) - Helps detect/prevent XSS, mixed-content, and other classes of attack. [CSP
|
|
4
|
+
- Content Security Policy (CSP) - Helps detect/prevent XSS, mixed-content, and other classes of attack. [CSP 2 Specification](http://www.w3.org/TR/CSP2/)
|
|
5
5
|
- HTTP Strict Transport Security (HSTS) - Ensures the browser never visits the http version of a website. Protects from SSLStrip/Firesheep attacks. [HSTS Specification](https://tools.ietf.org/html/rfc6797)
|
|
6
6
|
- X-Frame-Options (XFO) - Prevents your content from being framed and potentially clickjacked. [X-Frame-Options draft](https://tools.ietf.org/html/draft-ietf-websec-x-frame-options-02)
|
|
7
7
|
- X-XSS-Protection - [Cross site scripting heuristic filter for IE/Chrome](http://msdn.microsoft.com/en-us/library/dd565647\(v=vs.85\).aspx)
|
|
8
8
|
- X-Content-Type-Options - [Prevent content type sniffing](http://msdn.microsoft.com/en-us/library/ie/gg622941\(v=vs.85\).aspx)
|
|
9
9
|
- X-Download-Options - [Prevent file downloads opening](http://msdn.microsoft.com/en-us/library/ie/jj542450(v=vs.85).aspx)
|
|
10
10
|
- 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)
|
|
11
|
+
- Public Key Pinning - Pin certificate fingerprints in the browser to prevent man-in-the-middle attacks due to compromised Certificate Authorites. [Public Key Pinnning Specification](https://tools.ietf.org/html/draft-ietf-websec-key-pinning-21)
|
|
11
12
|
|
|
12
13
|
## Usage
|
|
13
14
|
|
|
@@ -21,6 +22,7 @@ The following methods are going to be called, unless they are provided in a `ski
|
|
|
21
22
|
|
|
22
23
|
* `:set_csp_header`
|
|
23
24
|
* `:set_hsts_header`
|
|
25
|
+
* `:set_hpkp_header`
|
|
24
26
|
* `:set_x_frame_options_header`
|
|
25
27
|
* `:set_x_xss_protection_header`
|
|
26
28
|
* `:set_x_content_type_options_header`
|
|
@@ -51,15 +53,24 @@ This gem makes a few assumptions about how you will use some features. For exam
|
|
|
51
53
|
:img_src => "https:",
|
|
52
54
|
:report_uri => '//example.com/uri-directive'
|
|
53
55
|
}
|
|
56
|
+
config.hpkp = {
|
|
57
|
+
:max_age => 60.days.to_i,
|
|
58
|
+
:include_subdomains => true,
|
|
59
|
+
:report_uri => '//example.com/uri-directive',
|
|
60
|
+
:pins => [
|
|
61
|
+
{:sha256 => 'abc'},
|
|
62
|
+
{:sha256 => '123'}
|
|
63
|
+
]
|
|
64
|
+
}
|
|
54
65
|
end
|
|
55
66
|
|
|
56
|
-
# and then
|
|
67
|
+
# and then include this in application_controller.rb
|
|
57
68
|
class ApplicationController < ActionController::Base
|
|
58
69
|
ensure_security_headers
|
|
59
70
|
end
|
|
60
71
|
```
|
|
61
72
|
|
|
62
|
-
Or
|
|
73
|
+
Or do the config as a parameter to `ensure_security_headers`
|
|
63
74
|
|
|
64
75
|
```ruby
|
|
65
76
|
ensure_security_headers(
|
|
@@ -298,6 +309,26 @@ console.log("will raise an exception if not in script_hashes.yml!")
|
|
|
298
309
|
<% end %>
|
|
299
310
|
```
|
|
300
311
|
|
|
312
|
+
### Public Key Pins
|
|
313
|
+
|
|
314
|
+
Be aware that pinning error reporting is governed by the same rules as everything else. If you have a pinning failure that tries to report back to the same origin, by definition this will not work.
|
|
315
|
+
|
|
316
|
+
```
|
|
317
|
+
config.hpkp = {
|
|
318
|
+
max_age: 60.days.to_i, # max_age is a required parameter
|
|
319
|
+
include_subdomains: true, # whether or not to apply pins to subdomains
|
|
320
|
+
# Per the spec, SHA256 hashes are the only currently supported format.
|
|
321
|
+
pins: [
|
|
322
|
+
{sha256: 'b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c'},
|
|
323
|
+
{sha256: '73a2c64f9545172c1195efb6616ca5f7afd1df6f245407cafb90de3998a1c97f'}
|
|
324
|
+
],
|
|
325
|
+
enforce: true, # defaults to false (report-only mode)
|
|
326
|
+
report_uri: '//example.com/uri-directive',
|
|
327
|
+
app_name: 'example',
|
|
328
|
+
tag_report_uri: true
|
|
329
|
+
}
|
|
330
|
+
```
|
|
331
|
+
|
|
301
332
|
### Using with Sinatra
|
|
302
333
|
|
|
303
334
|
Here's an example using SecureHeaders for Sinatra applications:
|
|
@@ -321,6 +352,7 @@ require 'secure_headers'
|
|
|
321
352
|
:img_src => "https: data:",
|
|
322
353
|
:frame_src => "https: http:.twimg.com http://itunes.apple.com"
|
|
323
354
|
}
|
|
355
|
+
config.hpkp = false
|
|
324
356
|
end
|
|
325
357
|
|
|
326
358
|
class Donkey < Sinatra::Application
|
|
@@ -31,7 +31,13 @@ module SecureHeaders
|
|
|
31
31
|
:reflected_xss
|
|
32
32
|
]
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
OTHER = [
|
|
35
|
+
:report_uri
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
SOURCE_DIRECTIVES = DIRECTIVES + NON_DEFAULT_SOURCES
|
|
39
|
+
|
|
40
|
+
ALL_DIRECTIVES = DIRECTIVES + NON_DEFAULT_SOURCES + OTHER
|
|
35
41
|
end
|
|
36
42
|
include Constants
|
|
37
43
|
|
|
@@ -102,7 +108,7 @@ module SecureHeaders
|
|
|
102
108
|
@config = config.inject({}) do |hash, (key, value)|
|
|
103
109
|
config_val = value.respond_to?(:call) ? value.call : value
|
|
104
110
|
|
|
105
|
-
if
|
|
111
|
+
if SOURCE_DIRECTIVES.include?(key) # directives need to be normalized to arrays of strings
|
|
106
112
|
config_val = config_val.split if config_val.is_a? String
|
|
107
113
|
if config_val.is_a?(Array)
|
|
108
114
|
config_val = config_val.map do |val|
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
module SecureHeaders
|
|
2
|
+
class PublicKeyPinsBuildError < StandardError; end
|
|
3
|
+
class PublicKeyPins < Header
|
|
4
|
+
module Constants
|
|
5
|
+
HPKP_HEADER_NAME = "Public-Key-Pins"
|
|
6
|
+
ENV_KEY = 'secure_headers.public_key_pins'
|
|
7
|
+
HASH_ALGORITHMS = [:sha256]
|
|
8
|
+
DIRECTIVES = [:max_age]
|
|
9
|
+
end
|
|
10
|
+
class << self
|
|
11
|
+
def symbol_to_hyphen_case sym
|
|
12
|
+
sym.to_s.gsub('_', '-')
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
include Constants
|
|
16
|
+
|
|
17
|
+
def initialize(config=nil)
|
|
18
|
+
@config = validate_config(config)
|
|
19
|
+
|
|
20
|
+
@pins = @config.fetch(:pins, nil)
|
|
21
|
+
@report_uri = @config.fetch(:report_uri, nil)
|
|
22
|
+
@app_name = @config.fetch(:app_name, nil)
|
|
23
|
+
@enforce = !!@config.fetch(:enforce, nil)
|
|
24
|
+
@include_subdomains = !!@config.fetch(:include_subdomains, nil)
|
|
25
|
+
@tag_report_uri = !!@config.fetch(:tag_report_uri, nil)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def name
|
|
29
|
+
base = HPKP_HEADER_NAME
|
|
30
|
+
if !@enforce
|
|
31
|
+
base += "-Report-Only"
|
|
32
|
+
end
|
|
33
|
+
base
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def value
|
|
37
|
+
header_value = [
|
|
38
|
+
generic_directives,
|
|
39
|
+
pin_directives,
|
|
40
|
+
report_uri_directive,
|
|
41
|
+
subdomain_directive
|
|
42
|
+
].compact.join('; ').strip
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def validate_config(config)
|
|
46
|
+
raise PublicKeyPinsBuildError.new("config must be a hash.") unless config.is_a? Hash
|
|
47
|
+
|
|
48
|
+
if !config[:max_age]
|
|
49
|
+
raise PublicKeyPinsBuildError.new("max-age is a required directive.")
|
|
50
|
+
elsif config[:max_age].to_s !~ /\A\d+\z/
|
|
51
|
+
raise PublicKeyPinsBuildError.new("max-age must be a number.
|
|
52
|
+
#{config[:max_age]} was supplied.")
|
|
53
|
+
elsif config[:pins] && config[:pins].length < 2
|
|
54
|
+
raise PublicKeyPinsBuildError.new("A minimum of 2 pins are required.")
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
config
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def pin_directives
|
|
61
|
+
return nil if @pins.nil?
|
|
62
|
+
@pins.collect do |pin|
|
|
63
|
+
pin.map do |token, hash|
|
|
64
|
+
"pin-#{token}=\"#{hash}\"" if HASH_ALGORITHMS.include?(token)
|
|
65
|
+
end
|
|
66
|
+
end.join('; ')
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def generic_directives
|
|
70
|
+
DIRECTIVES.collect do |directive_name|
|
|
71
|
+
build_directive(directive_name) if @config[directive_name]
|
|
72
|
+
end.join('; ')
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def build_directive(key)
|
|
76
|
+
"#{self.class.symbol_to_hyphen_case(key)}=#{@config[key]}"
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def report_uri_directive
|
|
80
|
+
return nil if @report_uri.nil?
|
|
81
|
+
|
|
82
|
+
if @tag_report_uri
|
|
83
|
+
@report_uri = "#{@report_uri}?enforce=#{@enforce}"
|
|
84
|
+
@report_uri += "&app_name=#{@app_name}" if @app_name
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
"report-uri=\"#{@report_uri}\""
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def subdomain_directive
|
|
92
|
+
@include_subdomains ? 'includeSubDomains' : nil
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
data/lib/secure_headers.rb
CHANGED
|
@@ -6,7 +6,7 @@ module SecureHeaders
|
|
|
6
6
|
class << self
|
|
7
7
|
attr_accessor :hsts, :x_frame_options, :x_content_type_options,
|
|
8
8
|
:x_xss_protection, :csp, :x_download_options, :script_hashes,
|
|
9
|
-
:x_permitted_cross_domain_policies
|
|
9
|
+
:x_permitted_cross_domain_policies, :hpkp
|
|
10
10
|
|
|
11
11
|
def configure &block
|
|
12
12
|
instance_eval &block
|
|
@@ -42,6 +42,7 @@ module SecureHeaders
|
|
|
42
42
|
self.secure_headers_options = options
|
|
43
43
|
before_filter :prep_script_hash
|
|
44
44
|
before_filter :set_hsts_header
|
|
45
|
+
before_filter :set_hpkp_header
|
|
45
46
|
before_filter :set_x_frame_options_header
|
|
46
47
|
before_filter :set_csp_header
|
|
47
48
|
before_filter :set_x_xss_protection_header
|
|
@@ -61,6 +62,7 @@ module SecureHeaders
|
|
|
61
62
|
def set_security_headers(options = self.class.secure_headers_options)
|
|
62
63
|
set_csp_header(request, options[:csp])
|
|
63
64
|
set_hsts_header(options[:hsts])
|
|
65
|
+
set_hpkp_header(options[:hpkp])
|
|
64
66
|
set_x_frame_options_header(options[:x_frame_options])
|
|
65
67
|
set_x_xss_protection_header(options[:x_xss_protection])
|
|
66
68
|
set_x_content_type_options_header(options[:x_content_type_options])
|
|
@@ -136,6 +138,16 @@ module SecureHeaders
|
|
|
136
138
|
set_a_header(:hsts, StrictTransportSecurity, options)
|
|
137
139
|
end
|
|
138
140
|
|
|
141
|
+
def set_hpkp_header(options=self.class.secure_headers_options[:hpkp])
|
|
142
|
+
return unless request.ssl?
|
|
143
|
+
config = self.class.options_for :hpkp, options
|
|
144
|
+
|
|
145
|
+
return if config == false || config.nil?
|
|
146
|
+
|
|
147
|
+
hpkp_header = PublicKeyPins.new(config)
|
|
148
|
+
set_header(hpkp_header)
|
|
149
|
+
end
|
|
150
|
+
|
|
139
151
|
def set_x_download_options_header(options=self.class.secure_headers_options[:x_download_options])
|
|
140
152
|
set_a_header(:x_download_options, XDownloadOptions, options)
|
|
141
153
|
end
|
|
@@ -168,6 +180,7 @@ end
|
|
|
168
180
|
|
|
169
181
|
require "secure_headers/version"
|
|
170
182
|
require "secure_headers/header"
|
|
183
|
+
require "secure_headers/headers/public_key_pins"
|
|
171
184
|
require "secure_headers/headers/content_security_policy"
|
|
172
185
|
require "secure_headers/headers/x_frame_options"
|
|
173
186
|
require "secure_headers/headers/strict_transport_security"
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module SecureHeaders
|
|
4
|
+
describe PublicKeyPins do
|
|
5
|
+
specify{ expect(PublicKeyPins.new(:max_age => 1234).name).to eq("Public-Key-Pins-Report-Only") }
|
|
6
|
+
specify{ expect(PublicKeyPins.new(:max_age => 1234, :enforce => true).name).to eq("Public-Key-Pins") }
|
|
7
|
+
|
|
8
|
+
specify { expect(PublicKeyPins.new({:max_age => 1234}).value).to eq("max-age=1234")}
|
|
9
|
+
specify { expect(PublicKeyPins.new(:max_age => 1234).value).to eq("max-age=1234")}
|
|
10
|
+
specify {
|
|
11
|
+
config = {:max_age => 1234, :pins => [{:sha256 => 'base64encodedpin1'}, {:sha256 => 'base64encodedpin2'}]}
|
|
12
|
+
header_value = "max-age=1234; pin-sha256=\"base64encodedpin1\"; pin-sha256=\"base64encodedpin2\""
|
|
13
|
+
expect(PublicKeyPins.new(config).value).to eq(header_value)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
context "with an invalid configuration" do
|
|
17
|
+
it "raises an exception when max-age is not provided" do
|
|
18
|
+
expect {
|
|
19
|
+
PublicKeyPins.new(:foo => 'bar')
|
|
20
|
+
}.to raise_error(PublicKeyPinsBuildError)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "raises an exception with an invalid max-age" do
|
|
24
|
+
expect {
|
|
25
|
+
PublicKeyPins.new(:max_age => 'abc123')
|
|
26
|
+
}.to raise_error(PublicKeyPinsBuildError)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it 'raises an exception with less than 2 pins' do
|
|
30
|
+
expect {
|
|
31
|
+
config = {:max_age => 1234, :pins => [{:sha256 => 'base64encodedpin'}]}
|
|
32
|
+
PublicKeyPins.new(config)
|
|
33
|
+
}.to raise_error(PublicKeyPinsBuildError)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -18,18 +18,13 @@ describe SecureHeaders do
|
|
|
18
18
|
allow(subject).to receive(:request).and_return(request)
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
ALL_HEADERS = Hash[[:hsts, :csp, :x_frame_options, :x_content_type_options, :x_xss_protection, :x_permitted_cross_domain_policies].map{|header| [header, false]}]
|
|
22
|
-
|
|
23
21
|
def stub_user_agent val
|
|
24
22
|
allow(request).to receive_message_chain(:env, :[]).and_return(val)
|
|
25
23
|
end
|
|
26
24
|
|
|
27
|
-
def options_for header
|
|
28
|
-
ALL_HEADERS.reject{|k,v| k == header}
|
|
29
|
-
end
|
|
30
|
-
|
|
31
25
|
def reset_config
|
|
32
26
|
::SecureHeaders::Configuration.configure do |config|
|
|
27
|
+
config.hpkp = nil
|
|
33
28
|
config.hsts = nil
|
|
34
29
|
config.x_frame_options = nil
|
|
35
30
|
config.x_content_type_options = nil
|
|
@@ -42,6 +37,7 @@ describe SecureHeaders do
|
|
|
42
37
|
|
|
43
38
|
def set_security_headers(subject)
|
|
44
39
|
subject.set_csp_header
|
|
40
|
+
subject.set_hpkp_header
|
|
45
41
|
subject.set_hsts_header
|
|
46
42
|
subject.set_x_frame_options_header
|
|
47
43
|
subject.set_x_content_type_options_header
|
|
@@ -71,6 +67,7 @@ describe SecureHeaders do
|
|
|
71
67
|
subject.set_csp_header
|
|
72
68
|
subject.set_x_frame_options_header
|
|
73
69
|
subject.set_hsts_header
|
|
70
|
+
subject.set_hpkp_header
|
|
74
71
|
subject.set_x_xss_protection_header
|
|
75
72
|
subject.set_x_content_type_options_header
|
|
76
73
|
subject.set_x_download_options_header
|
|
@@ -115,6 +112,17 @@ describe SecureHeaders do
|
|
|
115
112
|
subject.set_hsts_header({:include_subdomains => true})
|
|
116
113
|
end
|
|
117
114
|
|
|
115
|
+
it "does not set the HPKP header if disabled" do
|
|
116
|
+
should_not_assign_header(HPKP_HEADER_NAME)
|
|
117
|
+
subject.set_hpkp_header
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it "does not set the HPKP header if request is over HTTP" do
|
|
121
|
+
allow(subject).to receive_message_chain(:request, :ssl?).and_return(false)
|
|
122
|
+
should_not_assign_header(HPKP_HEADER_NAME)
|
|
123
|
+
subject.set_hpkp_header(:max_age => 1234)
|
|
124
|
+
end
|
|
125
|
+
|
|
118
126
|
it "does not set the CSP header if disabled" do
|
|
119
127
|
stub_user_agent(USER_AGENTS[:chrome])
|
|
120
128
|
should_not_assign_header(HEADER_NAME)
|
|
@@ -136,6 +144,7 @@ describe SecureHeaders do
|
|
|
136
144
|
it "does not set any headers when disabled" do
|
|
137
145
|
::SecureHeaders::Configuration.configure do |config|
|
|
138
146
|
config.hsts = false
|
|
147
|
+
config.hpkp = false
|
|
139
148
|
config.x_frame_options = false
|
|
140
149
|
config.x_content_type_options = false
|
|
141
150
|
config.x_xss_protection = false
|
|
@@ -196,6 +205,38 @@ describe SecureHeaders do
|
|
|
196
205
|
end
|
|
197
206
|
end
|
|
198
207
|
|
|
208
|
+
describe "#set_public_key_pins" do
|
|
209
|
+
it "sets the Public-Key-Pins header" do
|
|
210
|
+
should_assign_header(HPKP_HEADER_NAME + "-Report-Only", "max-age=1234")
|
|
211
|
+
subject.set_hpkp_header(:max_age => 1234)
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
it "allows you to enforce public key pinning" do
|
|
215
|
+
should_assign_header(HPKP_HEADER_NAME, "max-age=1234")
|
|
216
|
+
subject.set_hpkp_header(:max_age => 1234, :enforce => true)
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
it "allows you to specific a custom max-age value" do
|
|
220
|
+
should_assign_header(HPKP_HEADER_NAME + "-Report-Only", 'max-age=1234')
|
|
221
|
+
subject.set_hpkp_header(:max_age => 1234)
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
it "allows you to specify includeSubdomains" do
|
|
225
|
+
should_assign_header(HPKP_HEADER_NAME, "max-age=1234; includeSubDomains")
|
|
226
|
+
subject.set_hpkp_header(:max_age => 1234, :include_subdomains => true, :enforce => true)
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
it "allows you to specify a report-uri" do
|
|
230
|
+
should_assign_header(HPKP_HEADER_NAME, "max-age=1234; report-uri=\"https://foobar.com\"")
|
|
231
|
+
subject.set_hpkp_header(:max_age => 1234, :report_uri => "https://foobar.com", :enforce => true)
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
it "allows you to specify a report-uri with app_name" do
|
|
235
|
+
should_assign_header(HPKP_HEADER_NAME, "max-age=1234; report-uri=\"https://foobar.com?enforce=true&app_name=my_app\"")
|
|
236
|
+
subject.set_hpkp_header(:max_age => 1234, :report_uri => "https://foobar.com", :app_name => "my_app", :tag_report_uri => true, :enforce => true)
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
|
|
199
240
|
describe "#set_x_xss_protection" do
|
|
200
241
|
it "sets the X-XSS-Protection header" do
|
|
201
242
|
should_assign_header(X_XSS_PROTECTION_HEADER_NAME, SecureHeaders::XXssProtection::Constants::DEFAULT_VALUE)
|
data/spec/spec_helper.rb
CHANGED
|
@@ -7,6 +7,7 @@ if defined?(Coveralls)
|
|
|
7
7
|
Coveralls.wear!
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
+
include ::SecureHeaders::PublicKeyPins::Constants
|
|
10
11
|
include ::SecureHeaders::StrictTransportSecurity::Constants
|
|
11
12
|
include ::SecureHeaders::ContentSecurityPolicy::Constants
|
|
12
13
|
include ::SecureHeaders::XFrameOptions::Constants
|
metadata
CHANGED
|
@@ -1,30 +1,27 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: secure_headers
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
5
|
-
prerelease:
|
|
4
|
+
version: 2.1.0
|
|
6
5
|
platform: ruby
|
|
7
6
|
authors:
|
|
8
7
|
- Neil Matatall
|
|
9
8
|
autorequire:
|
|
10
9
|
bindir: bin
|
|
11
10
|
cert_chain: []
|
|
12
|
-
date: 2015-
|
|
11
|
+
date: 2015-05-07 00:00:00.000000000 Z
|
|
13
12
|
dependencies:
|
|
14
13
|
- !ruby/object:Gem::Dependency
|
|
15
14
|
name: rake
|
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
|
17
|
-
none: false
|
|
18
16
|
requirements:
|
|
19
|
-
- -
|
|
17
|
+
- - ">="
|
|
20
18
|
- !ruby/object:Gem::Version
|
|
21
19
|
version: '0'
|
|
22
20
|
type: :development
|
|
23
21
|
prerelease: false
|
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
-
none: false
|
|
26
23
|
requirements:
|
|
27
|
-
- -
|
|
24
|
+
- - ">="
|
|
28
25
|
- !ruby/object:Gem::Version
|
|
29
26
|
version: '0'
|
|
30
27
|
description: Security related headers all in one gem.
|
|
@@ -34,10 +31,10 @@ executables: []
|
|
|
34
31
|
extensions: []
|
|
35
32
|
extra_rdoc_files: []
|
|
36
33
|
files:
|
|
37
|
-
- .gitignore
|
|
38
|
-
- .ruby-gemset
|
|
39
|
-
- .ruby-version
|
|
40
|
-
- .travis.yml
|
|
34
|
+
- ".gitignore"
|
|
35
|
+
- ".ruby-gemset"
|
|
36
|
+
- ".ruby-version"
|
|
37
|
+
- ".travis.yml"
|
|
41
38
|
- Gemfile
|
|
42
39
|
- LICENSE
|
|
43
40
|
- README.md
|
|
@@ -130,6 +127,7 @@ files:
|
|
|
130
127
|
- lib/secure_headers/header.rb
|
|
131
128
|
- lib/secure_headers/headers/content_security_policy.rb
|
|
132
129
|
- lib/secure_headers/headers/content_security_policy/script_hash_middleware.rb
|
|
130
|
+
- lib/secure_headers/headers/public_key_pins.rb
|
|
133
131
|
- lib/secure_headers/headers/strict_transport_security.rb
|
|
134
132
|
- lib/secure_headers/headers/x_content_type_options.rb
|
|
135
133
|
- lib/secure_headers/headers/x_download_options.rb
|
|
@@ -144,6 +142,7 @@ files:
|
|
|
144
142
|
- secure_headers.gemspec
|
|
145
143
|
- spec/lib/secure_headers/headers/content_security_policy/script_hash_middleware_spec.rb
|
|
146
144
|
- spec/lib/secure_headers/headers/content_security_policy_spec.rb
|
|
145
|
+
- spec/lib/secure_headers/headers/public_key_pins_spec.rb
|
|
147
146
|
- spec/lib/secure_headers/headers/strict_transport_security_spec.rb
|
|
148
147
|
- spec/lib/secure_headers/headers/x_content_type_options_spec.rb
|
|
149
148
|
- spec/lib/secure_headers/headers/x_download_options_spec.rb
|
|
@@ -156,32 +155,32 @@ files:
|
|
|
156
155
|
homepage: https://github.com/twitter/secureheaders
|
|
157
156
|
licenses:
|
|
158
157
|
- Apache Public License 2.0
|
|
158
|
+
metadata: {}
|
|
159
159
|
post_install_message:
|
|
160
160
|
rdoc_options: []
|
|
161
161
|
require_paths:
|
|
162
162
|
- lib
|
|
163
163
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
164
|
-
none: false
|
|
165
164
|
requirements:
|
|
166
|
-
- -
|
|
165
|
+
- - ">="
|
|
167
166
|
- !ruby/object:Gem::Version
|
|
168
167
|
version: '0'
|
|
169
168
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
170
|
-
none: false
|
|
171
169
|
requirements:
|
|
172
|
-
- -
|
|
170
|
+
- - ">="
|
|
173
171
|
- !ruby/object:Gem::Version
|
|
174
172
|
version: '0'
|
|
175
173
|
requirements: []
|
|
176
174
|
rubyforge_project:
|
|
177
|
-
rubygems_version:
|
|
175
|
+
rubygems_version: 2.2.3
|
|
178
176
|
signing_key:
|
|
179
|
-
specification_version:
|
|
177
|
+
specification_version: 4
|
|
180
178
|
summary: Add easily configured security headers to responses including content-security-policy,
|
|
181
179
|
x-frame-options, strict-transport-security, etc.
|
|
182
180
|
test_files:
|
|
183
181
|
- spec/lib/secure_headers/headers/content_security_policy/script_hash_middleware_spec.rb
|
|
184
182
|
- spec/lib/secure_headers/headers/content_security_policy_spec.rb
|
|
183
|
+
- spec/lib/secure_headers/headers/public_key_pins_spec.rb
|
|
185
184
|
- spec/lib/secure_headers/headers/strict_transport_security_spec.rb
|
|
186
185
|
- spec/lib/secure_headers/headers/x_content_type_options_spec.rb
|
|
187
186
|
- spec/lib/secure_headers/headers/x_download_options_spec.rb
|