secure_headers 0.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.
Potentially problematic release.
This version of secure_headers might be problematic. Click here for more details.
- data/.gitignore +17 -0
- data/.rvmrc +1 -0
- data/.travis.yml +5 -0
- data/Gemfile +13 -0
- data/Guardfile +10 -0
- data/HISTORY.md +22 -0
- data/LICENSE +202 -0
- data/README.md +318 -0
- data/Rakefile +127 -0
- data/app/controllers/content_security_policy_controller.rb +44 -0
- data/config/curl-ca-bundle.crt +5420 -0
- data/config/routes.rb +3 -0
- data/lib/secure_headers.rb +115 -0
- data/lib/secure_headers/headers/content_security_policy.rb +300 -0
- data/lib/secure_headers/headers/strict_transport_security.rb +53 -0
- data/lib/secure_headers/headers/x_content_type_options.rb +40 -0
- data/lib/secure_headers/headers/x_frame_options.rb +40 -0
- data/lib/secure_headers/headers/x_xss_protection.rb +54 -0
- data/lib/secure_headers/railtie.rb +37 -0
- data/lib/secure_headers/version.rb +3 -0
- data/secure-headers.gemspec +23 -0
- data/spec/controllers/content_security_policy_controller_spec.rb +74 -0
- data/spec/lib/secure_headers/headers/content_security_policy_spec.rb +382 -0
- data/spec/lib/secure_headers/headers/strict_transport_security_spec.rb +66 -0
- data/spec/lib/secure_headers/headers/x_content_type_options_spec.rb +35 -0
- data/spec/lib/secure_headers/headers/x_frame_options_spec.rb +38 -0
- data/spec/lib/secure_headers/headers/x_xss_protection_spec.rb +41 -0
- data/spec/lib/secure_headers_spec.rb +252 -0
- data/spec/spec_helper.rb +25 -0
- metadata +116 -0
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module SecureHeaders
|
4
|
+
describe StrictTransportSecurity do
|
5
|
+
specify{ StrictTransportSecurity.new.name.should == "Strict-Transport-Security" }
|
6
|
+
|
7
|
+
describe "#value" do
|
8
|
+
it "sets Strict Transport Security headers" do
|
9
|
+
s = StrictTransportSecurity.new
|
10
|
+
s.value.should == StrictTransportSecurity::Constants::DEFAULT_VALUE
|
11
|
+
end
|
12
|
+
|
13
|
+
it "allows you to specify includeSubdomains" do
|
14
|
+
s = StrictTransportSecurity.new(:max_age => HSTS_MAX_AGE, :include_subdomains => true)
|
15
|
+
s.value.should == "max-age=#{HSTS_MAX_AGE}; includeSubdomains"
|
16
|
+
end
|
17
|
+
|
18
|
+
it "accepts a string value and returns verbatim" do
|
19
|
+
s = StrictTransportSecurity.new('max-age=1234')
|
20
|
+
s.value.should == "max-age=1234"
|
21
|
+
end
|
22
|
+
|
23
|
+
it "allows you to specify max-age" do
|
24
|
+
age = '8675309'
|
25
|
+
s = StrictTransportSecurity.new(:max_age => age)
|
26
|
+
s.value.should == "max-age=#{age}"
|
27
|
+
end
|
28
|
+
|
29
|
+
context "with an invalid configuration" do
|
30
|
+
context "with a hash argument" do
|
31
|
+
it "raises an exception with an invalid max-age" do
|
32
|
+
lambda {
|
33
|
+
StrictTransportSecurity.new(:max_age => 'abc123')
|
34
|
+
}.should raise_error(STSBuildError)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "raises an exception if max-age is not supplied" do
|
38
|
+
lambda {
|
39
|
+
StrictTransportSecurity.new(:includeSubdomains => true)
|
40
|
+
}.should raise_error(STSBuildError)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context "with a string argument" do
|
45
|
+
it "raises an exception with an invalid max-age" do
|
46
|
+
lambda {
|
47
|
+
StrictTransportSecurity.new('max-age=abc123')
|
48
|
+
}.should raise_error(STSBuildError)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "raises an exception if max-age is not supplied" do
|
52
|
+
lambda {
|
53
|
+
StrictTransportSecurity.new('includeSubdomains')
|
54
|
+
}.should raise_error(STSBuildError)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "raises an exception with an invalid format" do
|
58
|
+
lambda {
|
59
|
+
StrictTransportSecurity.new('max-age=123includeSubdomains')
|
60
|
+
}.should raise_error(STSBuildError)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module SecureHeaders
|
2
|
+
describe XContentTypeOptions do
|
3
|
+
specify{ XContentTypeOptions.new.name.should == "X-Content-Type-Options" }
|
4
|
+
|
5
|
+
describe "#value" do
|
6
|
+
specify { XContentTypeOptions.new.value.should == XContentTypeOptions::Constants::DEFAULT_VALUE}
|
7
|
+
specify { XContentTypeOptions.new("nosniff").value.should == "nosniff"}
|
8
|
+
specify { XContentTypeOptions.new(:value => 'nosniff').value.should == "nosniff"}
|
9
|
+
|
10
|
+
context "invalid configuration values" do
|
11
|
+
it "accepts nosniff" do
|
12
|
+
lambda {
|
13
|
+
XContentTypeOptions.new("nosniff")
|
14
|
+
}.should_not raise_error
|
15
|
+
|
16
|
+
lambda {
|
17
|
+
XContentTypeOptions.new(:value => "nosniff")
|
18
|
+
}.should_not raise_error
|
19
|
+
end
|
20
|
+
|
21
|
+
it "accepts nil" do
|
22
|
+
lambda {
|
23
|
+
XContentTypeOptions.new
|
24
|
+
}.should_not raise_error
|
25
|
+
end
|
26
|
+
|
27
|
+
it "doesn't accept anything besides no-sniff" do
|
28
|
+
lambda {
|
29
|
+
XContentTypeOptions.new("donkey")
|
30
|
+
}.should raise_error(XContentTypeOptionsBuildError)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module SecureHeaders
|
4
|
+
describe XFrameOptions do
|
5
|
+
specify{ XFrameOptions.new.name.should == "X-FRAME-OPTIONS" }
|
6
|
+
|
7
|
+
describe "#value" do
|
8
|
+
specify { XFrameOptions.new.value.should == XFrameOptions::Constants::DEFAULT_VALUE}
|
9
|
+
specify { XFrameOptions.new("SAMEORIGIN").value.should == "SAMEORIGIN"}
|
10
|
+
specify { XFrameOptions.new(:value => 'DENY').value.should == "DENY"}
|
11
|
+
|
12
|
+
context "with invalid configuration" do
|
13
|
+
it "allows SAMEORIGIN" do
|
14
|
+
lambda {
|
15
|
+
XFrameOptions.new("SAMEORIGIN").value
|
16
|
+
}.should_not raise_error(XFOBuildError)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "allows DENY" do
|
20
|
+
lambda {
|
21
|
+
XFrameOptions.new("DENY").value
|
22
|
+
}.should_not raise_error(XFOBuildError)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "allows ALLOW-FROM*" do
|
26
|
+
lambda {
|
27
|
+
XFrameOptions.new("ALLOW-FROM: example.com").value
|
28
|
+
}.should_not raise_error(XFOBuildError)
|
29
|
+
end
|
30
|
+
it "does not allow garbage" do
|
31
|
+
lambda {
|
32
|
+
XFrameOptions.new("I like turtles").value
|
33
|
+
}.should raise_error(XFOBuildError)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module SecureHeaders
|
2
|
+
describe XXssProtection do
|
3
|
+
specify { XXssProtection.new.name.should == X_XSS_PROTECTION_HEADER_NAME}
|
4
|
+
specify { XXssProtection.new.value.should == "1"}
|
5
|
+
specify { XXssProtection.new("0").value.should == "0"}
|
6
|
+
specify { XXssProtection.new(:value => 1, :mode => 'block').value.should == '1; mode=block' }
|
7
|
+
|
8
|
+
context "with invalid configuration" do
|
9
|
+
it "should raise an error when providing a string that is not valid" do
|
10
|
+
lambda {
|
11
|
+
XXssProtection.new("asdf")
|
12
|
+
}.should raise_error(XXssProtectionBuildError)
|
13
|
+
|
14
|
+
lambda {
|
15
|
+
XXssProtection.new("asdf; mode=donkey")
|
16
|
+
}.should raise_error(XXssProtectionBuildError)
|
17
|
+
end
|
18
|
+
|
19
|
+
context "when using a hash value" do
|
20
|
+
it "should raise an error if no value key is supplied" do
|
21
|
+
lambda {
|
22
|
+
XXssProtection.new(:mode => 'block')
|
23
|
+
}.should raise_error(XXssProtectionBuildError)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should raise an error if an invalid key is supplied" do
|
27
|
+
lambda {
|
28
|
+
XXssProtection.new(:value => 123)
|
29
|
+
}.should raise_error(XXssProtectionBuildError)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should raise an error if mode != block" do
|
33
|
+
lambda {
|
34
|
+
XXssProtection.new(:value => 1, :mode => "donkey")
|
35
|
+
}.should raise_error(XXssProtectionBuildError)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,252 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
# half spec test, half integration test...
|
4
|
+
describe SecureHeaders do
|
5
|
+
class DummyClass
|
6
|
+
include ::SecureHeaders
|
7
|
+
end
|
8
|
+
|
9
|
+
subject {DummyClass.new}
|
10
|
+
let(:headers) {double}
|
11
|
+
let(:response) {double(:headers => headers)}
|
12
|
+
let(:max_age) {99}
|
13
|
+
let(:request) {double(:ssl? => true, :url => 'https://example.com')}
|
14
|
+
|
15
|
+
before(:each) do
|
16
|
+
stub_user_agent(nil)
|
17
|
+
headers.stub(:[])
|
18
|
+
subject.stub(:response).and_return(response)
|
19
|
+
subject.stub(:request).and_return(request)
|
20
|
+
end
|
21
|
+
|
22
|
+
ALL_HEADERS = Hash[[:hsts, :csp, :x_frame_options, :x_content_type_options, :x_xss_protection].map{|header| [header, false]}]
|
23
|
+
USER_AGENTS = {
|
24
|
+
:firefox => 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:14.0) Gecko/20100101 Firefox/14.0.1',
|
25
|
+
:chrome => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.56 Safari/536.5',
|
26
|
+
:ie => 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/5.0)',
|
27
|
+
:opera => 'Opera/9.80 (Windows NT 6.1; U; es-ES) Presto/2.9.181 Version/12.00',
|
28
|
+
:ios5 => "Mozilla/5.0 (iPhone; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3"
|
29
|
+
}
|
30
|
+
|
31
|
+
describe "#set_header" do
|
32
|
+
it "sets the given header and value" do
|
33
|
+
headers.should_receive(:[]=).with("header", "value")
|
34
|
+
subject.set_header("header", "value")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def should_assign_header name, value
|
39
|
+
subject.should_receive(:set_header).with(name, value)
|
40
|
+
end
|
41
|
+
|
42
|
+
def should_not_assign_header name
|
43
|
+
subject.should_not_receive(:set_header).with(name, anything)
|
44
|
+
end
|
45
|
+
|
46
|
+
def stub_user_agent val
|
47
|
+
request.stub_chain(:env, :[]).and_return(val)
|
48
|
+
end
|
49
|
+
|
50
|
+
def options_for header
|
51
|
+
ALL_HEADERS.reject{|k,v| k == header}
|
52
|
+
end
|
53
|
+
|
54
|
+
def reset_config
|
55
|
+
::SecureHeaders::Configuration.configure do |config|
|
56
|
+
config.hsts = nil
|
57
|
+
config.x_frame_options = nil
|
58
|
+
config.x_content_type_options = nil
|
59
|
+
config.x_xss_protection = nil
|
60
|
+
config.csp = nil
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "#ensure_security_headers" do
|
65
|
+
it "sets a before filter" do
|
66
|
+
options = {}
|
67
|
+
DummyClass.should_receive(:before_filter).with(:set_security_headers)
|
68
|
+
DummyClass.ensure_security_headers(options)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "#set_security_headers" do
|
73
|
+
before(:each) do
|
74
|
+
SecureHeaders::ContentSecurityPolicy.stub(:new).and_return(double.as_null_object)
|
75
|
+
end
|
76
|
+
USER_AGENTS.each do |name, useragent|
|
77
|
+
it "sets all default headers for #{name} (smoke test)" do
|
78
|
+
stub_user_agent(useragent)
|
79
|
+
number_of_headers = case name
|
80
|
+
when :ie
|
81
|
+
5
|
82
|
+
when :opera
|
83
|
+
4
|
84
|
+
when :ios5
|
85
|
+
3 # csp is disabled for ios5
|
86
|
+
else
|
87
|
+
4
|
88
|
+
end
|
89
|
+
|
90
|
+
subject.should_receive(:set_header).exactly(number_of_headers).times # a request for a given header
|
91
|
+
subject.set_security_headers
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
it "does not set the X-Content-Type-Options when disabled" do
|
96
|
+
stub_user_agent(USER_AGENTS[:ie])
|
97
|
+
should_not_assign_header(X_CONTENT_TYPE_OPTIONS_HEADER_NAME)
|
98
|
+
subject.set_security_headers(:x_content_type_options => false)
|
99
|
+
end
|
100
|
+
|
101
|
+
it "does not set the X-XSS-PROTECTION when disabled" do
|
102
|
+
stub_user_agent(USER_AGENTS[:ie])
|
103
|
+
should_not_assign_header(X_XSS_PROTECTION_HEADER_NAME)
|
104
|
+
subject.set_security_headers(:x_xss_protection => false)
|
105
|
+
end
|
106
|
+
|
107
|
+
it "does not set the X-FRAME-OPTIONS header if disabled" do
|
108
|
+
should_not_assign_header(XFO_HEADER_NAME)
|
109
|
+
subject.set_security_headers(:x_frame_options => false)
|
110
|
+
end
|
111
|
+
|
112
|
+
it "does not set the hsts header if disabled" do
|
113
|
+
should_not_assign_header(HSTS_HEADER_NAME)
|
114
|
+
subject.set_security_headers(:hsts => false)
|
115
|
+
end
|
116
|
+
|
117
|
+
it "does not set the hsts header the request is over HTTP" do
|
118
|
+
subject.stub_chain(:request, :ssl?).and_return(false)
|
119
|
+
should_not_assign_header(HSTS_HEADER_NAME)
|
120
|
+
subject.set_security_headers(:hsts => {:include_subdomains => true})
|
121
|
+
end
|
122
|
+
|
123
|
+
it "does not set the CSP header if disabled" do
|
124
|
+
stub_user_agent(USER_AGENTS[:chrome])
|
125
|
+
should_not_assign_header(WEBKIT_CSP_HEADER_NAME)
|
126
|
+
subject.set_security_headers(options_for(:csp).merge(:csp => false))
|
127
|
+
end
|
128
|
+
|
129
|
+
# apparently iOS5 safari with CSP in enforce mode causes nothing to render
|
130
|
+
# it has no effect in report-only mode (as in no report is sent)
|
131
|
+
it "does not set CSP header if using ios5" do
|
132
|
+
stub_user_agent(USER_AGENTS[:ios5])
|
133
|
+
subject.should_not_receive(:set_csp_header)
|
134
|
+
subject.set_security_headers(options_for(:csp))
|
135
|
+
end
|
136
|
+
|
137
|
+
context "when disabled by configuration settings" do
|
138
|
+
it "does not set the X-Content-Type-Options when disabled" do
|
139
|
+
::SecureHeaders::Configuration.configure do |config|
|
140
|
+
config.hsts = false
|
141
|
+
config.x_frame_options = false
|
142
|
+
config.x_content_type_options = false
|
143
|
+
config.x_xss_protection = false
|
144
|
+
config.csp = false
|
145
|
+
end
|
146
|
+
subject.should_not_receive(:set_header)
|
147
|
+
subject.set_security_headers
|
148
|
+
reset_config
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
describe "#set_x_frame_options_header" do
|
154
|
+
it "sets the X-FRAME-OPTIONS header" do
|
155
|
+
should_assign_header(XFO_HEADER_NAME, SecureHeaders::XFrameOptions::Constants::DEFAULT_VALUE)
|
156
|
+
subject.set_x_frame_options_header
|
157
|
+
end
|
158
|
+
|
159
|
+
it "allows a custom X-FRAME-OPTIONS header" do
|
160
|
+
should_assign_header(XFO_HEADER_NAME, "DENY")
|
161
|
+
subject.set_x_frame_options_header(:value => 'DENY')
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
context "when using IE" do
|
166
|
+
before(:each) do
|
167
|
+
stub_user_agent(USER_AGENTS[:ie])
|
168
|
+
end
|
169
|
+
|
170
|
+
describe "#set_x_xss_protection" do
|
171
|
+
it "sets the XSS protection header" do
|
172
|
+
should_assign_header(X_XSS_PROTECTION_HEADER_NAME, '1')
|
173
|
+
subject.set_x_xss_protection_header
|
174
|
+
end
|
175
|
+
|
176
|
+
it "sets a custom X-XSS-PROTECTION header" do
|
177
|
+
should_assign_header(X_XSS_PROTECTION_HEADER_NAME, '0')
|
178
|
+
subject.set_x_xss_protection_header("0")
|
179
|
+
end
|
180
|
+
|
181
|
+
it "sets the block flag" do
|
182
|
+
should_assign_header(X_XSS_PROTECTION_HEADER_NAME, '1; mode=block')
|
183
|
+
subject.set_x_xss_protection_header(:mode => 'block', :value => 1)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
describe "#set_x_content_type_options" do
|
188
|
+
it "sets the X-Content-Type-Options" do
|
189
|
+
should_assign_header(X_CONTENT_TYPE_OPTIONS_HEADER_NAME, 'nosniff')
|
190
|
+
subject.set_x_content_type_options_header
|
191
|
+
end
|
192
|
+
|
193
|
+
it "lets you override X-Content-Type-Options" do
|
194
|
+
should_assign_header(X_CONTENT_TYPE_OPTIONS_HEADER_NAME, 'nosniff')
|
195
|
+
subject.set_x_content_type_options_header(:value => 'nosniff')
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
describe "#set_csp_header" do
|
201
|
+
context "when using Firefox" do
|
202
|
+
it "sets CSP headers" do
|
203
|
+
stub_user_agent(USER_AGENTS[:firefox])
|
204
|
+
should_assign_header(FIREFOX_CSP_HEADER_NAME + "-Report-Only", FIREFOX_CSP_HEADER)
|
205
|
+
subject.set_csp_header request
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
context "when using Chrome" do
|
210
|
+
it "sets default CSP header" do
|
211
|
+
stub_user_agent(USER_AGENTS[:chrome])
|
212
|
+
should_assign_header(WEBKIT_CSP_HEADER_NAME + "-Report-Only", WEBKIT_CSP_HEADER)
|
213
|
+
subject.set_csp_header request
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
context "when using a browser besides chrome/firefox" do
|
218
|
+
it "sets the CSP header" do
|
219
|
+
stub_user_agent(USER_AGENTS[:opera])
|
220
|
+
should_assign_header(WEBKIT_CSP_HEADER_NAME + "-Report-Only", WEBKIT_CSP_HEADER)
|
221
|
+
subject.set_csp_header request
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
context "when using the experimental key" do
|
226
|
+
before(:each) do
|
227
|
+
stub_user_agent(USER_AGENTS[:chrome])
|
228
|
+
@opts = {
|
229
|
+
:enforce => true,
|
230
|
+
:default_src => 'self',
|
231
|
+
:script_src => 'https://mycdn.example.com',
|
232
|
+
:experimental => {
|
233
|
+
:script_src => 'self',
|
234
|
+
}
|
235
|
+
}
|
236
|
+
end
|
237
|
+
|
238
|
+
it "does not set the header in enforce mode if experimental is supplied, but enforce is disabled" do
|
239
|
+
opts = @opts.merge(:enforce => false)
|
240
|
+
should_assign_header(WEBKIT_CSP_HEADER_NAME + "-Report-Only", anything)
|
241
|
+
should_not_assign_header(WEBKIT_CSP_HEADER_NAME)
|
242
|
+
subject.set_csp_header request, opts
|
243
|
+
end
|
244
|
+
|
245
|
+
it "sets a header in enforce mode as well as report-only mode" do
|
246
|
+
should_assign_header(WEBKIT_CSP_HEADER_NAME, anything)
|
247
|
+
should_assign_header(WEBKIT_CSP_HEADER_NAME + "-Report-Only", anything)
|
248
|
+
subject.set_csp_header request, @opts
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'spork'
|
3
|
+
|
4
|
+
unless Spork.using_spork?
|
5
|
+
require 'simplecov'
|
6
|
+
SimpleCov.start do
|
7
|
+
add_filter "spec"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
Spork.prefork do
|
12
|
+
require 'pry'
|
13
|
+
require 'rspec'
|
14
|
+
end
|
15
|
+
|
16
|
+
Spork.each_run do
|
17
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'secure_headers')
|
18
|
+
require File.join(File.dirname(__FILE__), '..', 'app', 'controllers', 'content_security_policy_controller')
|
19
|
+
include ::SecureHeaders::StrictTransportSecurity::Constants
|
20
|
+
include ::SecureHeaders::ContentSecurityPolicy::Constants
|
21
|
+
include ::SecureHeaders::XFrameOptions::Constants
|
22
|
+
include ::SecureHeaders::XXssProtection::Constants
|
23
|
+
include ::SecureHeaders::XContentTypeOptions::Constants
|
24
|
+
end
|
25
|
+
|