secure_headers 2.0.0.pre → 2.0.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.
- data/.travis.yml +7 -1
- data/Gemfile +4 -4
- data/README.md +14 -32
- data/Rakefile +11 -0
- data/fixtures/rails_3_2_12/config/initializers/secure_headers.rb +1 -0
- data/fixtures/rails_3_2_12/spec/controllers/other_things_controller_spec.rb +5 -0
- data/fixtures/rails_3_2_12/spec/controllers/things_controller_spec.rb +5 -0
- data/fixtures/rails_3_2_12_no_init/spec/controllers/other_things_controller_spec.rb +5 -0
- data/fixtures/rails_3_2_12_no_init/spec/controllers/things_controller_spec.rb +5 -0
- data/fixtures/rails_4_1_8/Gemfile +5 -0
- data/fixtures/rails_4_1_8/README.rdoc +28 -0
- data/fixtures/rails_4_1_8/Rakefile +6 -0
- data/fixtures/rails_4_1_8/app/controllers/application_controller.rb +4 -0
- data/fixtures/rails_4_1_8/app/controllers/concerns/.keep +0 -0
- data/fixtures/rails_4_1_8/app/controllers/other_things_controller.rb +5 -0
- data/fixtures/rails_4_1_8/app/controllers/things_controller.rb +5 -0
- data/fixtures/rails_4_1_8/app/models/.keep +0 -0
- data/fixtures/rails_4_1_8/app/models/concerns/.keep +0 -0
- data/fixtures/rails_4_1_8/app/views/layouts/application.html.erb +11 -0
- data/fixtures/rails_4_1_8/app/views/other_things/index.html.erb +2 -0
- data/fixtures/rails_4_1_8/app/views/things/index.html.erb +1 -0
- data/fixtures/rails_4_1_8/config/application.rb +15 -0
- data/fixtures/rails_4_1_8/config/boot.rb +4 -0
- data/fixtures/rails_4_1_8/config/environment.rb +5 -0
- data/fixtures/rails_4_1_8/config/environments/test.rb +10 -0
- data/fixtures/rails_4_1_8/config/initializers/secure_headers.rb +17 -0
- data/fixtures/rails_4_1_8/config/routes.rb +4 -0
- data/fixtures/rails_4_1_8/config/script_hashes.yml +5 -0
- data/fixtures/rails_4_1_8/config/secrets.yml +22 -0
- data/fixtures/rails_4_1_8/config.ru +4 -0
- data/fixtures/rails_4_1_8/lib/assets/.keep +0 -0
- data/fixtures/rails_4_1_8/lib/tasks/.keep +0 -0
- data/fixtures/rails_4_1_8/log/.keep +0 -0
- data/fixtures/rails_4_1_8/spec/controllers/other_things_controller_spec.rb +83 -0
- data/fixtures/rails_4_1_8/spec/controllers/things_controller_spec.rb +59 -0
- data/fixtures/rails_4_1_8/spec/spec_helper.rb +15 -0
- data/fixtures/rails_4_1_8/vendor/assets/javascripts/.keep +0 -0
- data/fixtures/rails_4_1_8/vendor/assets/stylesheets/.keep +0 -0
- data/lib/secure_headers/headers/content_security_policy.rb +8 -2
- data/lib/secure_headers/headers/x_permitted_cross_domain_policies.rb +40 -0
- data/lib/secure_headers/railtie.rb +13 -0
- data/lib/secure_headers/version.rb +1 -1
- data/lib/secure_headers/view_helper.rb +1 -1
- data/lib/secure_headers.rb +9 -1
- data/secure_headers.gemspec +4 -4
- data/spec/lib/secure_headers/headers/x_download_options_spec.rb +1 -1
- data/spec/lib/secure_headers/headers/x_permitted_cross_domain_policies_spec.rb +64 -0
- data/spec/lib/secure_headers_spec.rb +22 -7
- data/spec/spec_helper.rb +1 -0
- metadata +53 -18
- checksums.yaml +0 -7
- data/Guardfile +0 -8
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
|
@@ -4,12 +4,12 @@ gemspec
|
|
|
4
4
|
|
|
5
5
|
group :test do
|
|
6
6
|
gem 'rails', '3.2.12'
|
|
7
|
-
gem 'sqlite3', :
|
|
8
|
-
gem 'jdbc-sqlite3', :
|
|
7
|
+
gem 'sqlite3', :platforms => [:ruby, :mswin, :mingw]
|
|
8
|
+
gem 'jdbc-sqlite3', :platforms => [:jruby]
|
|
9
9
|
gem 'rspec-rails', '>= 3.1'
|
|
10
10
|
gem 'rspec', '>= 3.1'
|
|
11
|
-
gem 'guard-rspec', :platform => [:ruby_19, :ruby_20, :ruby_21]
|
|
12
11
|
gem 'growl'
|
|
13
12
|
gem 'rb-fsevent'
|
|
14
|
-
gem 'coveralls', :
|
|
13
|
+
gem 'coveralls', :platforms => [:ruby_19]
|
|
14
|
+
gem 'i18n', '< 0.7.0', :platforms => [:ruby_18]
|
|
15
15
|
end
|
data/README.md
CHANGED
|
@@ -1,41 +1,17 @@
|
|
|
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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
## Installation
|
|
13
|
-
|
|
14
|
-
Add to your Gemfile
|
|
15
|
-
|
|
16
|
-
```ruby
|
|
17
|
-
gem 'secure_headers'
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
And then execute:
|
|
21
|
-
|
|
22
|
-
```console
|
|
23
|
-
$ bundle
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
Or install it yourself as:
|
|
27
|
-
|
|
28
|
-
```console
|
|
29
|
-
$ gem install secure_headers
|
|
30
|
-
```
|
|
9
|
+
- X-Download-Options - [Prevent file downloads opening](http://msdn.microsoft.com/en-us/library/ie/jj542450(v=vs.85).aspx)
|
|
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)
|
|
31
11
|
|
|
32
12
|
## Usage
|
|
33
13
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
- `ensure_security_headers`: will set security-related headers automatically based on the configuration below.
|
|
37
|
-
|
|
38
|
-
By default, it will set all of the headers listed in the options section below unless specified.
|
|
14
|
+
- `ensure_security_headers` in a controller will set security-related headers automatically based on the configuration below.
|
|
39
15
|
|
|
40
16
|
### Disabling
|
|
41
17
|
|
|
@@ -48,6 +24,8 @@ The following methods are going to be called, unless they are provided in a `ski
|
|
|
48
24
|
* `:set_x_frame_options_header`
|
|
49
25
|
* `:set_x_xss_protection_header`
|
|
50
26
|
* `:set_x_content_type_options_header`
|
|
27
|
+
* `:set_x_download_options_header`
|
|
28
|
+
* `:set_x_permitted_cross_domain_policies_header`
|
|
51
29
|
|
|
52
30
|
### Bonus Features
|
|
53
31
|
|
|
@@ -65,6 +43,8 @@ This gem makes a few assumptions about how you will use some features. For exam
|
|
|
65
43
|
config.x_frame_options = 'DENY'
|
|
66
44
|
config.x_content_type_options = "nosniff"
|
|
67
45
|
config.x_xss_protection = {:value => 1, :mode => 'block'}
|
|
46
|
+
config.x_download_options = 'noopen'
|
|
47
|
+
config.x_permitted_cross_domain_policies = 'none'
|
|
68
48
|
config.csp = {
|
|
69
49
|
:default_src => "https: self",
|
|
70
50
|
:frame_src => "https: http:.twimg.com http://itunes.apple.com",
|
|
@@ -106,14 +86,12 @@ This configuration will likely work for most applications without modification.
|
|
|
106
86
|
:x_frame_options => {:value => 'SAMEORIGIN'}
|
|
107
87
|
:x_xss_protection => {:value => 1, :mode => 'block'} # set the :mode option to false to use "warning only" mode
|
|
108
88
|
:x_content_type_options => {:value => 'nosniff'}
|
|
89
|
+
:x_download_options => {:value => 'noopen'}
|
|
90
|
+
:x_permitted_cross_domain_policies => {:value => 'none'}
|
|
109
91
|
```
|
|
110
92
|
|
|
111
93
|
### Content Security Policy (CSP)
|
|
112
94
|
|
|
113
|
-
All browsers will receive the webkit csp header except Firefox, which gets its own header.
|
|
114
|
-
See [WebKit specification](http://www.w3.org/TR/CSP/)
|
|
115
|
-
and [Mozilla CSP specification](https://wiki.mozilla.org/Security/CSP/Specification)
|
|
116
|
-
|
|
117
95
|
```ruby
|
|
118
96
|
:csp => {
|
|
119
97
|
:enforce => false, # sets header to report-only, by default
|
|
@@ -335,6 +313,8 @@ require 'secure_headers'
|
|
|
335
313
|
config.x_frame_options = 'DENY'
|
|
336
314
|
config.x_content_type_options = "nosniff"
|
|
337
315
|
config.x_xss_protection = {:value => 1, :mode => false}
|
|
316
|
+
config.x_download_options = 'noopen'
|
|
317
|
+
config.x_permitted_cross_domain_policies = 'none'
|
|
338
318
|
config.csp = {
|
|
339
319
|
:default_src => "https: inline eval",
|
|
340
320
|
:report_uri => '//example.com/uri-directive',
|
|
@@ -390,6 +370,8 @@ def before_load
|
|
|
390
370
|
config.x_frame_options = 'DENY'
|
|
391
371
|
config.x_content_type_options = "nosniff"
|
|
392
372
|
config.x_xss_protection = {:value => '1', :mode => false}
|
|
373
|
+
config.x_download_options = 'noopen'
|
|
374
|
+
config.x_permitted_cross_domain_policies = 'none'
|
|
393
375
|
config.csp = {
|
|
394
376
|
:default_src => "https: inline eval",
|
|
395
377
|
:report_uri => '//example.com/uri-directive',
|
data/Rakefile
CHANGED
|
@@ -33,6 +33,17 @@ task :all_spec => :spec do
|
|
|
33
33
|
fail "Header tests with app not using initializer failed"
|
|
34
34
|
Dir.chdir pwd
|
|
35
35
|
end
|
|
36
|
+
|
|
37
|
+
Dir.chdir pwd
|
|
38
|
+
Dir.chdir 'fixtures/rails_4_1_8'
|
|
39
|
+
puts Dir.pwd
|
|
40
|
+
puts `bundle install >> /dev/null; bundle exec rspec spec`
|
|
41
|
+
|
|
42
|
+
unless $? == 0
|
|
43
|
+
fail "Header tests with Rails 4 failed"
|
|
44
|
+
Dir.chdir pwd
|
|
45
|
+
end
|
|
46
|
+
|
|
36
47
|
end
|
|
37
48
|
|
|
38
49
|
begin
|
|
@@ -67,6 +67,11 @@ describe OtherThingsController, :type => :controller do
|
|
|
67
67
|
expect(@env['X-Content-Type-Options']).to eq("nosniff")
|
|
68
68
|
end
|
|
69
69
|
|
|
70
|
+
it "sets the X-Permitted-Cross-Domain-Policies" do
|
|
71
|
+
get '/'
|
|
72
|
+
expect(@env['X-Permitted-Cross-Domain-Policies']).to eq("none")
|
|
73
|
+
end
|
|
74
|
+
|
|
70
75
|
context "using IE" do
|
|
71
76
|
it "sets the X-Content-Type-Options header" do
|
|
72
77
|
@env['HTTP_USER_AGENT'] = "Mozilla/5.0 (compatible; MSIE 10.6; Windows NT 6.1; Trident/5.0; InfoPath.2; SLCC1; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 2.0.50727) 3gpp-gba UNTRUSTED/1.0"
|
|
@@ -38,6 +38,11 @@ describe ThingsController, :type => :controller do
|
|
|
38
38
|
expect(response.headers['X-Content-Type-Options']).to eq("nosniff")
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
+
it "sets the X-Permitted-Cross-Domain-Policies" do
|
|
42
|
+
get :index
|
|
43
|
+
expect(response.headers['X-Permitted-Cross-Domain-Policies']).to eq("none")
|
|
44
|
+
end
|
|
45
|
+
|
|
41
46
|
context "using IE" do
|
|
42
47
|
it "sets the X-Content-Type-Options header" do
|
|
43
48
|
request.env['HTTP_USER_AGENT'] = "Mozilla/5.0 (compatible; MSIE 10.6; Windows NT 6.1; Trident/5.0; InfoPath.2; SLCC1; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 2.0.50727) 3gpp-gba UNTRUSTED/1.0"
|
|
@@ -34,6 +34,11 @@ describe OtherThingsController, :type => :controller do
|
|
|
34
34
|
expect(response.headers['X-Content-Type-Options']).to eq(SecureHeaders::XContentTypeOptions::Constants::DEFAULT_VALUE)
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
+
it "sets the X-Permitted-Cross-Domain-Policies" do
|
|
38
|
+
get :index
|
|
39
|
+
expect(response.headers['X-Permitted-Cross-Domain-Policies']).to eq("none")
|
|
40
|
+
end
|
|
41
|
+
|
|
37
42
|
context "using IE" do
|
|
38
43
|
it "sets the X-Content-Type-Options header" do
|
|
39
44
|
request.env['HTTP_USER_AGENT'] = "Mozilla/5.0 (compatible; MSIE 10.6; Windows NT 6.1; Trident/5.0; InfoPath.2; SLCC1; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 2.0.50727) 3gpp-gba UNTRUSTED/1.0"
|
|
@@ -38,6 +38,11 @@ describe ThingsController, :type => :controller do
|
|
|
38
38
|
expect(response.headers['X-Content-Type-Options']).to eq(SecureHeaders::XContentTypeOptions::Constants::DEFAULT_VALUE)
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
+
it "sets the X-Permitted-Cross-Domain-Policies" do
|
|
42
|
+
get :index
|
|
43
|
+
expect(response.headers['X-Permitted-Cross-Domain-Policies']).to eq("none")
|
|
44
|
+
end
|
|
45
|
+
|
|
41
46
|
context "using IE" do
|
|
42
47
|
it "sets the X-Content-Type-Options header" do
|
|
43
48
|
request.env['HTTP_USER_AGENT'] = "Mozilla/5.0 (compatible; MSIE 10.6; Windows NT 6.1; Trident/5.0; InfoPath.2; SLCC1; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 2.0.50727) 3gpp-gba UNTRUSTED/1.0"
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
== README
|
|
2
|
+
|
|
3
|
+
This README would normally document whatever steps are necessary to get the
|
|
4
|
+
application up and running.
|
|
5
|
+
|
|
6
|
+
Things you may want to cover:
|
|
7
|
+
|
|
8
|
+
* Ruby version
|
|
9
|
+
|
|
10
|
+
* System dependencies
|
|
11
|
+
|
|
12
|
+
* Configuration
|
|
13
|
+
|
|
14
|
+
* Database creation
|
|
15
|
+
|
|
16
|
+
* Database initialization
|
|
17
|
+
|
|
18
|
+
* How to run the test suite
|
|
19
|
+
|
|
20
|
+
* Services (job queues, cache servers, search engines, etc.)
|
|
21
|
+
|
|
22
|
+
* Deployment instructions
|
|
23
|
+
|
|
24
|
+
* ...
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
Please feel free to use a different markup language if you do not plan to run
|
|
28
|
+
<tt>rake doc:app</tt>.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
things
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require File.expand_path('../boot', __FILE__)
|
|
2
|
+
|
|
3
|
+
require "action_controller/railtie"
|
|
4
|
+
require "sprockets/railtie"
|
|
5
|
+
|
|
6
|
+
# Require the gems listed in Gemfile, including any gems
|
|
7
|
+
# you've limited to :test, :development, or :production.
|
|
8
|
+
Bundler.require(*Rails.groups)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
module Rails418
|
|
12
|
+
class Application < Rails::Application
|
|
13
|
+
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
Rails418::Application.configure do
|
|
2
|
+
config.cache_classes = true
|
|
3
|
+
config.eager_load = false
|
|
4
|
+
config.serve_static_assets = true
|
|
5
|
+
config.static_cache_control = 'public, max-age=3600'
|
|
6
|
+
config.consider_all_requests_local = true
|
|
7
|
+
config.action_controller.perform_caching = false
|
|
8
|
+
config.action_dispatch.show_exceptions = false
|
|
9
|
+
config.action_controller.allow_forgery_protection = false
|
|
10
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
::SecureHeaders::Configuration.configure do |config|
|
|
2
|
+
config.hsts = { :max_age => 10.years.to_i.to_s, :include_subdomains => false }
|
|
3
|
+
config.x_frame_options = 'DENY'
|
|
4
|
+
config.x_content_type_options = "nosniff"
|
|
5
|
+
config.x_xss_protection = {:value => 0}
|
|
6
|
+
config.x_permitted_cross_domain_policies = 'none'
|
|
7
|
+
csp = {
|
|
8
|
+
:default_src => "self",
|
|
9
|
+
:script_src => "self nonce",
|
|
10
|
+
:disable_fill_missing => true,
|
|
11
|
+
:report_uri => 'somewhere',
|
|
12
|
+
:script_hash_middleware => true,
|
|
13
|
+
:enforce => false # false means warnings only
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
config.csp = csp
|
|
17
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Be sure to restart your server when you modify this file.
|
|
2
|
+
|
|
3
|
+
# Your secret key is used for verifying the integrity of signed cookies.
|
|
4
|
+
# If you change this key, all old signed cookies will become invalid!
|
|
5
|
+
|
|
6
|
+
# Make sure the secret is at least 30 characters and all random,
|
|
7
|
+
# no regular words or you'll be exposed to dictionary attacks.
|
|
8
|
+
# You can use `rake secret` to generate a secure secret key.
|
|
9
|
+
|
|
10
|
+
# Make sure the secrets in this file are kept private
|
|
11
|
+
# if you're sharing your code publicly.
|
|
12
|
+
|
|
13
|
+
development:
|
|
14
|
+
secret_key_base: ddba38f932720d8f18257f2a05dc278963a29cf569c45aa97ff4e9fc9bbc78af5a03fcf135caad45caee66ac09f8f9913c1f5e338a61213f420eefa8dd6363d2
|
|
15
|
+
|
|
16
|
+
test:
|
|
17
|
+
secret_key_base: f73abd7eab84fa7af5a2fc0a9c2727c5bad47433e51aa0c9c6b0782dac176a8e7f337e1f93adc6d6fc17027e67a533040b6408e54d72dea2eec6e5b9820dbcb9
|
|
18
|
+
|
|
19
|
+
# Do not keep production secrets in the repository,
|
|
20
|
+
# instead read values from the environment.
|
|
21
|
+
production:
|
|
22
|
+
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
require 'secure_headers/headers/content_security_policy/script_hash_middleware'
|
|
4
|
+
|
|
5
|
+
describe OtherThingsController, :type => :controller do
|
|
6
|
+
include Rack::Test::Methods
|
|
7
|
+
|
|
8
|
+
def app
|
|
9
|
+
OtherThingsController.action(:index)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def request(opts = {})
|
|
13
|
+
options = opts.merge(
|
|
14
|
+
{
|
|
15
|
+
'HTTPS' => 'on',
|
|
16
|
+
'HTTP_USER_AGENT' => "Mozilla/5.0 (compatible; MSIE 10.6; Windows NT 6.1; Trident/5.0; InfoPath.2; SLCC1; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 2.0.50727) 3gpp-gba UNTRUSTED/1.0"
|
|
17
|
+
}
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
Rack::MockRequest.env_for('/', options)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
describe "headers" do
|
|
26
|
+
before(:each) do
|
|
27
|
+
_, @env = app.call(request)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "sets the X-XSS-Protection header" do
|
|
31
|
+
get '/'
|
|
32
|
+
expect(@env['X-XSS-Protection']).to eq('0')
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "sets the X-Frame-Options header" do
|
|
36
|
+
get '/'
|
|
37
|
+
expect(@env['X-Frame-Options']).to eq('DENY')
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "sets the CSP header with a local reference to a nonce" do
|
|
41
|
+
middleware = ::SecureHeaders::ContentSecurityPolicy::ScriptHashMiddleware.new(app)
|
|
42
|
+
_, env = middleware.call(request(@env))
|
|
43
|
+
expect(env['Content-Security-Policy-Report-Only']).to match(/script-src[^;]*'nonce-[a-zA-Z0-9\+\/=]{44}'/)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "sets the required hashes to whitelist inline script" do
|
|
47
|
+
middleware = ::SecureHeaders::ContentSecurityPolicy::ScriptHashMiddleware.new(app)
|
|
48
|
+
_, env = middleware.call(request(@env))
|
|
49
|
+
hashes = ['sha256-VjDxT7saxd2FgaUQQTWw/jsTnvonaoCP/ACWDBTpyhU=', 'sha256-ZXAcP8a0y1pPMTJW8pUr43c+XBkgYQBwHOPvXk9mq5A=']
|
|
50
|
+
hashes.each do |hash|
|
|
51
|
+
expect(env['Content-Security-Policy-Report-Only']).to include(hash)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "sets the Strict-Transport-Security header" do
|
|
56
|
+
get '/'
|
|
57
|
+
expect(@env['Strict-Transport-Security']).to eq("max-age=315576000")
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "sets the X-Download-Options header" do
|
|
61
|
+
get '/'
|
|
62
|
+
expect(@env['X-Download-Options']).to eq('noopen')
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "sets the X-Content-Type-Options header" do
|
|
66
|
+
get '/'
|
|
67
|
+
expect(@env['X-Content-Type-Options']).to eq("nosniff")
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "sets the X-Permitted-Cross-Domain-Policies" do
|
|
71
|
+
get '/'
|
|
72
|
+
expect(@env['X-Permitted-Cross-Domain-Policies']).to eq("none")
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
context "using IE" do
|
|
76
|
+
it "sets the X-Content-Type-Options header" do
|
|
77
|
+
@env['HTTP_USER_AGENT'] = "Mozilla/5.0 (compatible; MSIE 10.6; Windows NT 6.1; Trident/5.0; InfoPath.2; SLCC1; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 2.0.50727) 3gpp-gba UNTRUSTED/1.0"
|
|
78
|
+
get '/'
|
|
79
|
+
expect(@env['X-Content-Type-Options']).to eq("nosniff")
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# config.action_dispatch.default_headers defaults to:
|
|
2
|
+
# {"X-Frame-Options"=>"SAMEORIGIN", "X-XSS-Protection"=>"1; mode=block", "X-Content-Type-Options"=>"nosniff"}
|
|
3
|
+
# so we want to set our specs to expect something else to ensure secureheaders is taking precedence
|
|
4
|
+
|
|
5
|
+
require 'spec_helper'
|
|
6
|
+
|
|
7
|
+
# This controller is meant to be something that inherits config from application controller
|
|
8
|
+
# all values are defaulted because no initializer is configured, and the values in app controller
|
|
9
|
+
# only provide csp => false
|
|
10
|
+
|
|
11
|
+
describe ThingsController, :type => :controller do
|
|
12
|
+
|
|
13
|
+
describe "headers" do
|
|
14
|
+
it "sets the X-XSS-Protection header" do
|
|
15
|
+
get :index
|
|
16
|
+
expect(response.headers['X-XSS-Protection']).to eq('0')
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "sets the X-Frame-Options header" do
|
|
20
|
+
get :index
|
|
21
|
+
expect(response.headers['X-Frame-Options']).to eq('DENY')
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "does not set CSP header" do
|
|
25
|
+
get :index
|
|
26
|
+
expect(response.headers['Content-Security-Policy-Report-Only']).to eq(nil)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
#mock ssl
|
|
30
|
+
it "sets the Strict-Transport-Security header" do
|
|
31
|
+
request.env['HTTPS'] = 'on'
|
|
32
|
+
get :index
|
|
33
|
+
expect(response.headers['Strict-Transport-Security']).to eq("max-age=315576000")
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "sets the X-Download-Options header" do
|
|
37
|
+
get :index
|
|
38
|
+
expect(response.headers['X-Download-Options']).to eq('noopen')
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "sets the X-Content-Type-Options header" do
|
|
42
|
+
get :index
|
|
43
|
+
expect(response.headers['X-Content-Type-Options']).to eq("nosniff")
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "sets the X-Permitted-Cross-Domain-Policies" do
|
|
47
|
+
get :index
|
|
48
|
+
expect(response.headers['X-Permitted-Cross-Domain-Policies']).to eq("none")
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
context "using IE" do
|
|
52
|
+
it "sets the X-Content-Type-Options header" do
|
|
53
|
+
request.env['HTTP_USER_AGENT'] = "Mozilla/5.0 (compatible; MSIE 10.6; Windows NT 6.1; Trident/5.0; InfoPath.2; SLCC1; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 2.0.50727) 3gpp-gba UNTRUSTED/1.0"
|
|
54
|
+
get :index
|
|
55
|
+
expect(response.headers['X-Content-Type-Options']).to eq("nosniff")
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
|
|
3
|
+
#uncomment the following line to use spork with the debugger
|
|
4
|
+
#require 'spork/ext/ruby-debug'
|
|
5
|
+
|
|
6
|
+
# Spork.prefork do
|
|
7
|
+
# Loading more in this block will cause your tests to run faster. However,
|
|
8
|
+
# if you change any configuration or code from libraries loaded here, you'll
|
|
9
|
+
# need to restart spork for it take effect.
|
|
10
|
+
# This file is copied to spec/ when you run 'rails generate rspec:install'
|
|
11
|
+
ENV["RAILS_ENV"] ||= 'test'
|
|
12
|
+
require File.expand_path("../../config/environment", __FILE__)
|
|
13
|
+
require 'rspec/rails'
|
|
14
|
+
# end
|
|
15
|
+
|
|
File without changes
|
|
File without changes
|
|
@@ -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,40 @@
|
|
|
1
|
+
module SecureHeaders
|
|
2
|
+
class XPCDPBuildError < StandardError; end
|
|
3
|
+
class XPermittedCrossDomainPolicies < Header
|
|
4
|
+
module Constants
|
|
5
|
+
XPCDP_HEADER_NAME = "X-Permitted-Cross-Domain-Policies"
|
|
6
|
+
DEFAULT_VALUE = 'none'
|
|
7
|
+
VALID_POLICIES = %w(all none master-only by-content-type by-ftp-filename)
|
|
8
|
+
end
|
|
9
|
+
include Constants
|
|
10
|
+
|
|
11
|
+
def initialize(config = nil)
|
|
12
|
+
@config = config
|
|
13
|
+
validate_config unless @config.nil?
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def name
|
|
17
|
+
XPCDP_HEADER_NAME
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def value
|
|
21
|
+
case @config
|
|
22
|
+
when NilClass
|
|
23
|
+
DEFAULT_VALUE
|
|
24
|
+
when String
|
|
25
|
+
@config
|
|
26
|
+
else
|
|
27
|
+
@config[:value]
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def validate_config
|
|
34
|
+
value = @config.is_a?(Hash) ? @config[:value] : @config
|
|
35
|
+
unless VALID_POLICIES.include?(value.downcase)
|
|
36
|
+
raise XPCDPBuildError.new("Value can only be one of #{VALID_POLICIES.join(', ')}")
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -3,9 +3,22 @@ if defined?(Rails::Railtie)
|
|
|
3
3
|
module SecureHeaders
|
|
4
4
|
class Railtie < Rails::Engine
|
|
5
5
|
isolate_namespace ::SecureHeaders if defined? isolate_namespace # rails 3.0
|
|
6
|
+
conflicting_headers = ['X-Frame-Options', 'X-XSS-Protection', 'X-Content-Type-Options',
|
|
7
|
+
'X-Permitted-Cross-Domain-Policies', 'X-Download-Options',
|
|
8
|
+
'X-Content-Type-Options', 'Strict-Transport-Security',
|
|
9
|
+
'Content-Security-Policy', 'Content-Security-Policy-Report-Only',
|
|
10
|
+
'X-Permitted-Cross-Domain-Policies','Public-Key-Pins','Public-Key-Pins-Report-Only']
|
|
11
|
+
|
|
6
12
|
initializer "secure_headers.action_controller" do
|
|
7
13
|
ActiveSupport.on_load(:action_controller) do
|
|
8
14
|
include ::SecureHeaders
|
|
15
|
+
|
|
16
|
+
unless Rails.application.config.action_dispatch.default_headers.nil?
|
|
17
|
+
conflicting_headers.each do |header|
|
|
18
|
+
Rails.application.config.action_dispatch.default_headers.delete(header)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
9
22
|
end
|
|
10
23
|
end
|
|
11
24
|
end
|
data/lib/secure_headers.rb
CHANGED
|
@@ -5,7 +5,8 @@ module SecureHeaders
|
|
|
5
5
|
module Configuration
|
|
6
6
|
class << self
|
|
7
7
|
attr_accessor :hsts, :x_frame_options, :x_content_type_options,
|
|
8
|
-
:x_xss_protection, :csp, :x_download_options, :script_hashes
|
|
8
|
+
:x_xss_protection, :csp, :x_download_options, :script_hashes,
|
|
9
|
+
:x_permitted_cross_domain_policies
|
|
9
10
|
|
|
10
11
|
def configure &block
|
|
11
12
|
instance_eval &block
|
|
@@ -46,6 +47,7 @@ module SecureHeaders
|
|
|
46
47
|
before_filter :set_x_xss_protection_header
|
|
47
48
|
before_filter :set_x_content_type_options_header
|
|
48
49
|
before_filter :set_x_download_options_header
|
|
50
|
+
before_filter :set_x_permitted_cross_domain_policies_header
|
|
49
51
|
end
|
|
50
52
|
|
|
51
53
|
# we can't use ||= because I'm overloading false => disable, nil => default
|
|
@@ -63,6 +65,7 @@ module SecureHeaders
|
|
|
63
65
|
set_x_xss_protection_header(options[:x_xss_protection])
|
|
64
66
|
set_x_content_type_options_header(options[:x_content_type_options])
|
|
65
67
|
set_x_download_options_header(options[:x_download_options])
|
|
68
|
+
set_x_permitted_cross_domain_policies_header(options[:x_permitted_cross_domain_policies])
|
|
66
69
|
end
|
|
67
70
|
|
|
68
71
|
# set_csp_header - uses the request accessor and SecureHeader::Configuration settings
|
|
@@ -137,6 +140,10 @@ module SecureHeaders
|
|
|
137
140
|
set_a_header(:x_download_options, XDownloadOptions, options)
|
|
138
141
|
end
|
|
139
142
|
|
|
143
|
+
def set_x_permitted_cross_domain_policies_header(options=self.class.secure_headers_options[:x_permitted_cross_domain_policies])
|
|
144
|
+
set_a_header(:x_permitted_cross_domain_policies, XPermittedCrossDomainPolicies, options)
|
|
145
|
+
end
|
|
146
|
+
|
|
140
147
|
private
|
|
141
148
|
|
|
142
149
|
def set_a_header(name, klass, options=nil)
|
|
@@ -167,6 +174,7 @@ require "secure_headers/headers/strict_transport_security"
|
|
|
167
174
|
require "secure_headers/headers/x_xss_protection"
|
|
168
175
|
require "secure_headers/headers/x_content_type_options"
|
|
169
176
|
require "secure_headers/headers/x_download_options"
|
|
177
|
+
require "secure_headers/headers/x_permitted_cross_domain_policies"
|
|
170
178
|
require "secure_headers/railtie"
|
|
171
179
|
require "secure_headers/hash_helper"
|
|
172
180
|
require "secure_headers/view_helper"
|
data/secure_headers.gemspec
CHANGED
|
@@ -8,10 +8,10 @@ Gem::Specification.new do |gem|
|
|
|
8
8
|
gem.version = SecureHeaders::VERSION
|
|
9
9
|
gem.authors = ["Neil Matatall"]
|
|
10
10
|
gem.email = ["neil.matatall@gmail.com"]
|
|
11
|
-
gem.description = %q{
|
|
12
|
-
gem.summary = %q{Add easily configured
|
|
13
|
-
including content
|
|
14
|
-
strict-transport-security
|
|
11
|
+
gem.description = %q{Security related headers all in one gem.}
|
|
12
|
+
gem.summary = %q{Add easily configured security headers to responses
|
|
13
|
+
including content-security-policy, x-frame-options,
|
|
14
|
+
strict-transport-security, etc.}
|
|
15
15
|
gem.homepage = "https://github.com/twitter/secureheaders"
|
|
16
16
|
gem.license = "Apache Public License 2.0"
|
|
17
17
|
gem.files = `git ls-files`.split($/)
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
module SecureHeaders
|
|
2
|
+
describe XPermittedCrossDomainPolicies do
|
|
3
|
+
specify { expect(XPermittedCrossDomainPolicies.new.name).to eq(XPermittedCrossDomainPolicies::Constants::XPCDP_HEADER_NAME)}
|
|
4
|
+
specify { expect(XPermittedCrossDomainPolicies.new.value).to eq("none")}
|
|
5
|
+
specify { expect(XPermittedCrossDomainPolicies.new('master-only').value).to eq('master-only')}
|
|
6
|
+
specify { expect(XPermittedCrossDomainPolicies.new(:value => 'master-only').value).to eq('master-only') }
|
|
7
|
+
|
|
8
|
+
context "valid configuration values" do
|
|
9
|
+
it "accepts 'all'" do
|
|
10
|
+
expect {
|
|
11
|
+
XPermittedCrossDomainPolicies.new("all")
|
|
12
|
+
}.not_to raise_error
|
|
13
|
+
|
|
14
|
+
expect {
|
|
15
|
+
XPermittedCrossDomainPolicies.new(:value => "all")
|
|
16
|
+
}.not_to raise_error
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "accepts 'by-ftp-filename'" do
|
|
20
|
+
expect {
|
|
21
|
+
XPermittedCrossDomainPolicies.new("by-ftp-filename")
|
|
22
|
+
}.not_to raise_error
|
|
23
|
+
|
|
24
|
+
expect {
|
|
25
|
+
XPermittedCrossDomainPolicies.new(:value => "by-ftp-filename")
|
|
26
|
+
}.not_to raise_error
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "accepts 'by-content-type'" do
|
|
30
|
+
expect {
|
|
31
|
+
XPermittedCrossDomainPolicies.new("by-content-type")
|
|
32
|
+
}.not_to raise_error
|
|
33
|
+
|
|
34
|
+
expect {
|
|
35
|
+
XPermittedCrossDomainPolicies.new(:value => "by-content-type")
|
|
36
|
+
}.not_to raise_error
|
|
37
|
+
end
|
|
38
|
+
it "accepts 'master-only'" do
|
|
39
|
+
expect {
|
|
40
|
+
XPermittedCrossDomainPolicies.new("master-only")
|
|
41
|
+
}.not_to raise_error
|
|
42
|
+
|
|
43
|
+
expect {
|
|
44
|
+
XPermittedCrossDomainPolicies.new(:value => "master-only")
|
|
45
|
+
}.not_to raise_error
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "accepts nil" do
|
|
49
|
+
expect {
|
|
50
|
+
XPermittedCrossDomainPolicies.new
|
|
51
|
+
}.not_to raise_error
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
context 'invlaid configuration values' do
|
|
56
|
+
|
|
57
|
+
it "doesn't accept invalid values" do
|
|
58
|
+
expect {
|
|
59
|
+
XPermittedCrossDomainPolicies.new("open")
|
|
60
|
+
}.to raise_error
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -18,16 +18,10 @@ 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].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|
|
|
33
27
|
config.hsts = nil
|
|
@@ -36,6 +30,7 @@ describe SecureHeaders do
|
|
|
36
30
|
config.x_xss_protection = nil
|
|
37
31
|
config.csp = nil
|
|
38
32
|
config.x_download_options = nil
|
|
33
|
+
config.x_permitted_cross_domain_policies = nil
|
|
39
34
|
end
|
|
40
35
|
end
|
|
41
36
|
|
|
@@ -46,6 +41,7 @@ describe SecureHeaders do
|
|
|
46
41
|
subject.set_x_content_type_options_header
|
|
47
42
|
subject.set_x_xss_protection_header
|
|
48
43
|
subject.set_x_download_options_header
|
|
44
|
+
subject.set_x_permitted_cross_domain_policies_header
|
|
49
45
|
end
|
|
50
46
|
|
|
51
47
|
describe "#set_header" do
|
|
@@ -64,7 +60,7 @@ describe SecureHeaders do
|
|
|
64
60
|
USER_AGENTS.each do |name, useragent|
|
|
65
61
|
it "sets all default headers for #{name} (smoke test)" do
|
|
66
62
|
stub_user_agent(useragent)
|
|
67
|
-
number_of_headers =
|
|
63
|
+
number_of_headers = 7
|
|
68
64
|
expect(subject).to receive(:set_header).exactly(number_of_headers).times # a request for a given header
|
|
69
65
|
subject.set_csp_header
|
|
70
66
|
subject.set_x_frame_options_header
|
|
@@ -72,6 +68,7 @@ describe SecureHeaders do
|
|
|
72
68
|
subject.set_x_xss_protection_header
|
|
73
69
|
subject.set_x_content_type_options_header
|
|
74
70
|
subject.set_x_download_options_header
|
|
71
|
+
subject.set_x_permitted_cross_domain_policies_header
|
|
75
72
|
end
|
|
76
73
|
end
|
|
77
74
|
|
|
@@ -96,6 +93,11 @@ describe SecureHeaders do
|
|
|
96
93
|
subject.set_x_frame_options_header(false)
|
|
97
94
|
end
|
|
98
95
|
|
|
96
|
+
it "does not set the X-Permitted-Cross-Domain-Policies header if disabled" do
|
|
97
|
+
should_not_assign_header(XPCDP_HEADER_NAME)
|
|
98
|
+
subject.set_x_permitted_cross_domain_policies_header(false)
|
|
99
|
+
end
|
|
100
|
+
|
|
99
101
|
it "does not set the HSTS header if disabled" do
|
|
100
102
|
should_not_assign_header(HSTS_HEADER_NAME)
|
|
101
103
|
subject.set_hsts_header(false)
|
|
@@ -133,6 +135,7 @@ describe SecureHeaders do
|
|
|
133
135
|
config.x_xss_protection = false
|
|
134
136
|
config.csp = false
|
|
135
137
|
config.x_download_options = false
|
|
138
|
+
config.x_permitted_cross_domain_policies = false
|
|
136
139
|
end
|
|
137
140
|
expect(subject).not_to receive(:set_header)
|
|
138
141
|
set_security_headers(subject)
|
|
@@ -249,4 +252,16 @@ describe SecureHeaders do
|
|
|
249
252
|
end
|
|
250
253
|
end
|
|
251
254
|
end
|
|
255
|
+
|
|
256
|
+
describe "#set_x_permitted_cross_domain_policies_header" do
|
|
257
|
+
it "sets the X-Permitted-Cross-Domain-Policies header" do
|
|
258
|
+
should_assign_header(XPCDP_HEADER_NAME, SecureHeaders::XPermittedCrossDomainPolicies::Constants::DEFAULT_VALUE)
|
|
259
|
+
subject.set_x_permitted_cross_domain_policies_header
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
it "allows a custom X-Permitted-Cross-Domain-Policies header" do
|
|
263
|
+
should_assign_header(XPCDP_HEADER_NAME, "master-only")
|
|
264
|
+
subject.set_x_permitted_cross_domain_policies_header(:value => 'master-only')
|
|
265
|
+
end
|
|
266
|
+
end
|
|
252
267
|
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -13,6 +13,7 @@ include ::SecureHeaders::XFrameOptions::Constants
|
|
|
13
13
|
include ::SecureHeaders::XXssProtection::Constants
|
|
14
14
|
include ::SecureHeaders::XContentTypeOptions::Constants
|
|
15
15
|
include ::SecureHeaders::XDownloadOptions::Constants
|
|
16
|
+
include ::SecureHeaders::XPermittedCrossDomainPolicies::Constants
|
|
16
17
|
|
|
17
18
|
USER_AGENTS = {
|
|
18
19
|
:firefox => 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:14.0) Gecko/20100101 Firefox/14.0.1',
|
metadata
CHANGED
|
@@ -1,42 +1,44 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: secure_headers
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.0.
|
|
4
|
+
version: 2.0.2
|
|
5
|
+
prerelease:
|
|
5
6
|
platform: ruby
|
|
6
7
|
authors:
|
|
7
8
|
- Neil Matatall
|
|
8
9
|
autorequire:
|
|
9
10
|
bindir: bin
|
|
10
11
|
cert_chain: []
|
|
11
|
-
date:
|
|
12
|
+
date: 2015-05-05 00:00:00.000000000 Z
|
|
12
13
|
dependencies:
|
|
13
14
|
- !ruby/object:Gem::Dependency
|
|
14
15
|
name: rake
|
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
|
17
|
+
none: false
|
|
16
18
|
requirements:
|
|
17
|
-
- -
|
|
19
|
+
- - ! '>='
|
|
18
20
|
- !ruby/object:Gem::Version
|
|
19
21
|
version: '0'
|
|
20
22
|
type: :development
|
|
21
23
|
prerelease: false
|
|
22
24
|
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
none: false
|
|
23
26
|
requirements:
|
|
24
|
-
- -
|
|
27
|
+
- - ! '>='
|
|
25
28
|
- !ruby/object:Gem::Version
|
|
26
29
|
version: '0'
|
|
27
|
-
description:
|
|
30
|
+
description: Security related headers all in one gem.
|
|
28
31
|
email:
|
|
29
32
|
- neil.matatall@gmail.com
|
|
30
33
|
executables: []
|
|
31
34
|
extensions: []
|
|
32
35
|
extra_rdoc_files: []
|
|
33
36
|
files:
|
|
34
|
-
-
|
|
35
|
-
-
|
|
36
|
-
-
|
|
37
|
-
-
|
|
37
|
+
- .gitignore
|
|
38
|
+
- .ruby-gemset
|
|
39
|
+
- .ruby-version
|
|
40
|
+
- .travis.yml
|
|
38
41
|
- Gemfile
|
|
39
|
-
- Guardfile
|
|
40
42
|
- LICENSE
|
|
41
43
|
- README.md
|
|
42
44
|
- Rakefile
|
|
@@ -94,6 +96,35 @@ files:
|
|
|
94
96
|
- fixtures/rails_3_2_12_no_init/vendor/assets/javascripts/.gitkeep
|
|
95
97
|
- fixtures/rails_3_2_12_no_init/vendor/assets/stylesheets/.gitkeep
|
|
96
98
|
- fixtures/rails_3_2_12_no_init/vendor/plugins/.gitkeep
|
|
99
|
+
- fixtures/rails_4_1_8/Gemfile
|
|
100
|
+
- fixtures/rails_4_1_8/README.rdoc
|
|
101
|
+
- fixtures/rails_4_1_8/Rakefile
|
|
102
|
+
- fixtures/rails_4_1_8/app/controllers/application_controller.rb
|
|
103
|
+
- fixtures/rails_4_1_8/app/controllers/concerns/.keep
|
|
104
|
+
- fixtures/rails_4_1_8/app/controllers/other_things_controller.rb
|
|
105
|
+
- fixtures/rails_4_1_8/app/controllers/things_controller.rb
|
|
106
|
+
- fixtures/rails_4_1_8/app/models/.keep
|
|
107
|
+
- fixtures/rails_4_1_8/app/models/concerns/.keep
|
|
108
|
+
- fixtures/rails_4_1_8/app/views/layouts/application.html.erb
|
|
109
|
+
- fixtures/rails_4_1_8/app/views/other_things/index.html.erb
|
|
110
|
+
- fixtures/rails_4_1_8/app/views/things/index.html.erb
|
|
111
|
+
- fixtures/rails_4_1_8/config.ru
|
|
112
|
+
- fixtures/rails_4_1_8/config/application.rb
|
|
113
|
+
- fixtures/rails_4_1_8/config/boot.rb
|
|
114
|
+
- fixtures/rails_4_1_8/config/environment.rb
|
|
115
|
+
- fixtures/rails_4_1_8/config/environments/test.rb
|
|
116
|
+
- fixtures/rails_4_1_8/config/initializers/secure_headers.rb
|
|
117
|
+
- fixtures/rails_4_1_8/config/routes.rb
|
|
118
|
+
- fixtures/rails_4_1_8/config/script_hashes.yml
|
|
119
|
+
- fixtures/rails_4_1_8/config/secrets.yml
|
|
120
|
+
- fixtures/rails_4_1_8/lib/assets/.keep
|
|
121
|
+
- fixtures/rails_4_1_8/lib/tasks/.keep
|
|
122
|
+
- fixtures/rails_4_1_8/log/.keep
|
|
123
|
+
- fixtures/rails_4_1_8/spec/controllers/other_things_controller_spec.rb
|
|
124
|
+
- fixtures/rails_4_1_8/spec/controllers/things_controller_spec.rb
|
|
125
|
+
- fixtures/rails_4_1_8/spec/spec_helper.rb
|
|
126
|
+
- fixtures/rails_4_1_8/vendor/assets/javascripts/.keep
|
|
127
|
+
- fixtures/rails_4_1_8/vendor/assets/stylesheets/.keep
|
|
97
128
|
- lib/secure_headers.rb
|
|
98
129
|
- lib/secure_headers/hash_helper.rb
|
|
99
130
|
- lib/secure_headers/header.rb
|
|
@@ -103,6 +134,7 @@ files:
|
|
|
103
134
|
- lib/secure_headers/headers/x_content_type_options.rb
|
|
104
135
|
- lib/secure_headers/headers/x_download_options.rb
|
|
105
136
|
- lib/secure_headers/headers/x_frame_options.rb
|
|
137
|
+
- lib/secure_headers/headers/x_permitted_cross_domain_policies.rb
|
|
106
138
|
- lib/secure_headers/headers/x_xss_protection.rb
|
|
107
139
|
- lib/secure_headers/padrino.rb
|
|
108
140
|
- lib/secure_headers/railtie.rb
|
|
@@ -116,6 +148,7 @@ files:
|
|
|
116
148
|
- spec/lib/secure_headers/headers/x_content_type_options_spec.rb
|
|
117
149
|
- spec/lib/secure_headers/headers/x_download_options_spec.rb
|
|
118
150
|
- spec/lib/secure_headers/headers/x_frame_options_spec.rb
|
|
151
|
+
- spec/lib/secure_headers/headers/x_permitted_cross_domain_policies_spec.rb
|
|
119
152
|
- spec/lib/secure_headers/headers/x_xss_protection_spec.rb
|
|
120
153
|
- spec/lib/secure_headers_spec.rb
|
|
121
154
|
- spec/spec_helper.rb
|
|
@@ -123,28 +156,29 @@ files:
|
|
|
123
156
|
homepage: https://github.com/twitter/secureheaders
|
|
124
157
|
licenses:
|
|
125
158
|
- Apache Public License 2.0
|
|
126
|
-
metadata: {}
|
|
127
159
|
post_install_message:
|
|
128
160
|
rdoc_options: []
|
|
129
161
|
require_paths:
|
|
130
162
|
- lib
|
|
131
163
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
164
|
+
none: false
|
|
132
165
|
requirements:
|
|
133
|
-
- -
|
|
166
|
+
- - ! '>='
|
|
134
167
|
- !ruby/object:Gem::Version
|
|
135
168
|
version: '0'
|
|
136
169
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
170
|
+
none: false
|
|
137
171
|
requirements:
|
|
138
|
-
- -
|
|
172
|
+
- - ! '>='
|
|
139
173
|
- !ruby/object:Gem::Version
|
|
140
|
-
version:
|
|
174
|
+
version: '0'
|
|
141
175
|
requirements: []
|
|
142
176
|
rubyforge_project:
|
|
143
|
-
rubygems_version:
|
|
177
|
+
rubygems_version: 1.8.23
|
|
144
178
|
signing_key:
|
|
145
|
-
specification_version:
|
|
146
|
-
summary: Add easily configured
|
|
147
|
-
|
|
179
|
+
specification_version: 3
|
|
180
|
+
summary: Add easily configured security headers to responses including content-security-policy,
|
|
181
|
+
x-frame-options, strict-transport-security, etc.
|
|
148
182
|
test_files:
|
|
149
183
|
- spec/lib/secure_headers/headers/content_security_policy/script_hash_middleware_spec.rb
|
|
150
184
|
- spec/lib/secure_headers/headers/content_security_policy_spec.rb
|
|
@@ -152,6 +186,7 @@ test_files:
|
|
|
152
186
|
- spec/lib/secure_headers/headers/x_content_type_options_spec.rb
|
|
153
187
|
- spec/lib/secure_headers/headers/x_download_options_spec.rb
|
|
154
188
|
- spec/lib/secure_headers/headers/x_frame_options_spec.rb
|
|
189
|
+
- spec/lib/secure_headers/headers/x_permitted_cross_domain_policies_spec.rb
|
|
155
190
|
- spec/lib/secure_headers/headers/x_xss_protection_spec.rb
|
|
156
191
|
- spec/lib/secure_headers_spec.rb
|
|
157
192
|
- spec/spec_helper.rb
|
checksums.yaml
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
SHA1:
|
|
3
|
-
metadata.gz: 4d41b253fa38de884f864558563330b9e707e2dc
|
|
4
|
-
data.tar.gz: 69b19dbc4ab124481e6f47dad73cd7a6497aa844
|
|
5
|
-
SHA512:
|
|
6
|
-
metadata.gz: fa7e778e7cb305a3273d4b3aa94bf8597972910da752b218ebf0779330c4c025c2906cec3974a410193db600fc899465a2da8bc7a8ca5720eb30ba95335e7a5d
|
|
7
|
-
data.tar.gz: 21934fb364794d3fc08e7dde201e04cb1253686e362e46ec370b06021007cb897fc3182de9a1ac646fa2448f4ce7a9f45b33da31f4d2a8690b76c42527bb9001
|
data/Guardfile
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
notification :growl
|
|
2
|
-
|
|
3
|
-
guard 'rspec', cmd: 'rspec' do
|
|
4
|
-
watch(%r{^spec/.+_spec\.rb$})
|
|
5
|
-
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
|
6
|
-
watch(%r{^app/controllers/(.+)\.rb$}) { |m| "spec/controllers/#{m[1]}_spec.rb" }
|
|
7
|
-
watch('spec/spec_helper.rb') { "spec" }
|
|
8
|
-
end
|