secure_headers 3.9.0 → 4.0.0.alpha01
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of secure_headers might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/.rspec +1 -0
- data/.rubocop.yml +3 -0
- data/.ruby-version +1 -1
- data/.travis.yml +8 -6
- data/CHANGELOG.md +2 -34
- data/CONTRIBUTING.md +1 -1
- data/Gemfile +7 -4
- data/Guardfile +1 -0
- data/README.md +4 -25
- data/Rakefile +22 -18
- data/docs/cookies.md +18 -5
- data/lib/secure_headers.rb +1 -2
- data/lib/secure_headers/configuration.rb +6 -16
- data/lib/secure_headers/hash_helper.rb +2 -1
- data/lib/secure_headers/headers/clear_site_data.rb +2 -1
- data/lib/secure_headers/headers/content_security_policy.rb +14 -60
- data/lib/secure_headers/headers/content_security_policy_config.rb +1 -1
- data/lib/secure_headers/headers/cookie.rb +22 -10
- data/lib/secure_headers/headers/policy_management.rb +57 -98
- data/lib/secure_headers/headers/public_key_pins.rb +4 -3
- data/lib/secure_headers/headers/referrer_policy.rb +1 -0
- data/lib/secure_headers/headers/strict_transport_security.rb +2 -1
- data/lib/secure_headers/headers/x_content_type_options.rb +1 -0
- data/lib/secure_headers/headers/x_download_options.rb +2 -1
- data/lib/secure_headers/headers/x_frame_options.rb +1 -0
- data/lib/secure_headers/headers/x_permitted_cross_domain_policies.rb +2 -1
- data/lib/secure_headers/headers/x_xss_protection.rb +2 -1
- data/lib/secure_headers/middleware.rb +10 -9
- data/lib/secure_headers/railtie.rb +7 -6
- data/lib/secure_headers/utils/cookies_config.rb +17 -18
- data/lib/secure_headers/view_helper.rb +2 -1
- data/lib/tasks/tasks.rake +2 -1
- data/secure_headers.gemspec +13 -3
- data/spec/lib/secure_headers/configuration_spec.rb +9 -8
- data/spec/lib/secure_headers/headers/clear_site_data_spec.rb +2 -1
- data/spec/lib/secure_headers/headers/content_security_policy_spec.rb +17 -53
- data/spec/lib/secure_headers/headers/cookie_spec.rb +58 -37
- data/spec/lib/secure_headers/headers/policy_management_spec.rb +20 -41
- data/spec/lib/secure_headers/headers/public_key_pins_spec.rb +7 -6
- data/spec/lib/secure_headers/headers/referrer_policy_spec.rb +4 -3
- data/spec/lib/secure_headers/headers/strict_transport_security_spec.rb +5 -4
- data/spec/lib/secure_headers/headers/x_content_type_options_spec.rb +2 -1
- data/spec/lib/secure_headers/headers/x_download_options_spec.rb +3 -2
- data/spec/lib/secure_headers/headers/x_frame_options_spec.rb +2 -1
- data/spec/lib/secure_headers/headers/x_permitted_cross_domain_policies_spec.rb +4 -3
- data/spec/lib/secure_headers/headers/x_xss_protection_spec.rb +4 -3
- data/spec/lib/secure_headers/middleware_spec.rb +18 -21
- data/spec/lib/secure_headers/view_helpers_spec.rb +5 -4
- data/spec/lib/secure_headers_spec.rb +92 -120
- data/spec/spec_helper.rb +9 -23
- data/upgrading-to-4-0.md +49 -0
- metadata +16 -11
- data/lib/secure_headers/headers/expect_certificate_transparency.rb +0 -70
- data/spec/lib/secure_headers/headers/expect_certificate_transparency_spec.rb +0 -42
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1cfa800eacf250583e379d13a9149d585bc2f48d
|
4
|
+
data.tar.gz: 3de8c81b1308ec9d1d53f822cff8eeb7e20b5af0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4c25ae5372ac00f74b0cae3b7de0a767a15b45f275bed64994c2cd7d078a2f0b52bdce562d14280984ad494fd008445d5d5448a3ac94694cd1f9778da3deeacc
|
7
|
+
data.tar.gz: 6fab2c382ed56f9a63dd118a34b617fb82b4ee4e9ef55f37d78e134ec9068c9ee1022ba0a94991d0b7b82ea756d78132d3c0dfc909e66d4068acde4f6d2673ff
|
data/.rspec
CHANGED
data/.rubocop.yml
ADDED
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.4.1
|
data/.travis.yml
CHANGED
@@ -2,15 +2,17 @@ language: ruby
|
|
2
2
|
|
3
3
|
rvm:
|
4
4
|
- ruby-head
|
5
|
-
- 2.4.
|
6
|
-
- 2.3.
|
5
|
+
- 2.4.1
|
6
|
+
- 2.3.4
|
7
7
|
- 2.2
|
8
|
-
- 2.1
|
9
|
-
- 2.0.0
|
10
|
-
- 1.9.3
|
11
|
-
- jruby-19mode
|
12
8
|
- jruby-head
|
13
9
|
|
10
|
+
env:
|
11
|
+
- SUITE=rspec spec
|
12
|
+
- SUITE=rubocop
|
13
|
+
|
14
|
+
script: bundle exec $SUITE
|
15
|
+
|
14
16
|
matrix:
|
15
17
|
allow_failures:
|
16
18
|
- rvm: jruby-head
|
data/CHANGELOG.md
CHANGED
@@ -1,38 +1,6 @@
|
|
1
|
-
##
|
1
|
+
## 4.x
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
## 3.8.0
|
6
|
-
|
7
|
-
Fixes semicolon injection issue reported by @mvgijssel see https://github.com/twitter/secure_headers/issues/418
|
8
|
-
|
9
|
-
## 3.7.4
|
10
|
-
|
11
|
-
Backport SameSite=None functionality into 3.x line
|
12
|
-
|
13
|
-
## 3.7.3
|
14
|
-
|
15
|
-
- Updates `Expect-CT` header to use a comma separator between directives, as specified in the most current spec.
|
16
|
-
|
17
|
-
## 3.7.2
|
18
|
-
|
19
|
-
- Adds support for `worker-src` CSP directive to 3.x line (https://github.com/twitter/secureheaders/pull/364)
|
20
|
-
|
21
|
-
## 3.7.1
|
22
|
-
|
23
|
-
Fix support for the sandbox attribute of CSP. `true` and `[]` represent the maximally restricted policy (`sandbox;`) and validate other values.
|
24
|
-
|
25
|
-
## 3.7.0
|
26
|
-
|
27
|
-
Adds support for the `Expect-CT` header (@jacobbednarz: https://github.com/twitter/secureheaders/pull/322)
|
28
|
-
|
29
|
-
## 3.6.7
|
30
|
-
|
31
|
-
Actually set manifest-src when configured. https://github.com/twitter/secureheaders/pull/339 Thanks @carlosantoniodasilva!
|
32
|
-
|
33
|
-
## 3.6.6
|
34
|
-
|
35
|
-
wat?
|
3
|
+
- See the [upgrading to 4.0](upgrading-to-4.0.md) guide. Lots of breaking changes.
|
36
4
|
|
37
5
|
## 3.6.5
|
38
6
|
|
data/CONTRIBUTING.md
CHANGED
@@ -30,7 +30,7 @@ Here are a few things you can do that will increase the likelihood of your pull
|
|
30
30
|
0. Ensure CI is green
|
31
31
|
0. Pull the latest code
|
32
32
|
0. Increment the version
|
33
|
-
0. Run `gem build
|
33
|
+
0. Run `gem build secure_headers.gemspec`
|
34
34
|
0. Bump the Gemfile and Gemfile.lock versions for an app which relies on this gem
|
35
35
|
0. Test behavior locally, branch deploy, whatever needs to happen
|
36
36
|
0. Run `bundle exec rake release`
|
data/Gemfile
CHANGED
@@ -1,19 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
source "https://rubygems.org"
|
2
3
|
|
3
4
|
gemspec
|
4
5
|
|
5
6
|
group :test do
|
6
|
-
gem "
|
7
|
-
gem "pry-nav"
|
7
|
+
gem "coveralls"
|
8
8
|
gem "json", "~> 1"
|
9
|
+
gem "pry-nav"
|
9
10
|
gem "rack", "~> 1"
|
10
11
|
gem "rspec"
|
11
|
-
gem "
|
12
|
+
gem "rubocop", "~> 0.47.0"
|
13
|
+
gem "rubocop-github"
|
12
14
|
gem "term-ansicolor", "< 1.4"
|
15
|
+
gem "tins", "~> 1.6.0" # 1.7 requires ruby 2.0
|
13
16
|
end
|
14
17
|
|
15
18
|
group :guard do
|
16
|
-
gem "guard-rspec", platforms: [:ruby_19, :ruby_20, :ruby_21, :ruby_22]
|
17
19
|
gem "growl"
|
20
|
+
gem "guard-rspec", platforms: [:ruby_19, :ruby_20, :ruby_21, :ruby_22, :ruby_23, :ruby_24]
|
18
21
|
gem "rb-fsevent"
|
19
22
|
end
|
data/Guardfile
CHANGED
data/README.md
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
# Secure Headers [![Build Status](https://travis-ci.org/twitter/secureheaders.svg?branch=master)](http://travis-ci.org/twitter/secureheaders) [![Code Climate](https://codeclimate.com/github/twitter/secureheaders.svg)](https://codeclimate.com/github/twitter/secureheaders) [![Coverage Status](https://coveralls.io/repos/twitter/secureheaders/badge.svg)](https://coveralls.io/r/twitter/secureheaders)
|
2
2
|
|
3
|
+
**master represents the unreleased 4.x line**. See the [upgrading to 4.x doc](upgrading-to-4-0.md) for instructions on how to upgrade. Bug fixes should go in the 3.x branch for now.
|
3
4
|
|
4
|
-
**The 3.x branch
|
5
|
+
**The [3.x](https://github.com/twitter/secureheaders/tree/2.x) branch is moving into maintenance mode**. See the [upgrading to 3.x doc](upgrading-to-3-0.md) for instructions on how to upgrade including the differences and benefits of using the 3.x branch.
|
5
6
|
|
6
|
-
**The [2.x branch](https://github.com/twitter/secureheaders/tree/2.x) will be maintained**. The documentation below only applies to the 3.x branch. See the 2.x [README](https://github.com/twitter/secureheaders/blob/2.x/README.md) for the old way of doing things.
|
7
|
+
**The [2.x branch](https://github.com/twitter/secureheaders/tree/2.x) will be not be maintained once 4.x is released**. The documentation below only applies to the 3.x branch. See the 2.x [README](https://github.com/twitter/secureheaders/blob/2.x/README.md) for the old way of doing things.
|
7
8
|
|
8
9
|
The gem will automatically apply several headers that are related to security. This includes:
|
9
10
|
- Content Security Policy (CSP) - Helps detect/prevent XSS, mixed-content, and other classes of attack. [CSP 2 Specification](http://www.w3.org/TR/CSP2/)
|
@@ -18,7 +19,6 @@ The gem will automatically apply several headers that are related to security.
|
|
18
19
|
- X-Permitted-Cross-Domain-Policies - [Restrict Adobe Flash Player's access to data](https://www.adobe.com/devnet/adobe-media-server/articles/cross-domain-xml-for-streaming.html)
|
19
20
|
- Referrer-Policy - [Referrer Policy draft](https://w3c.github.io/webappsec-referrer-policy/)
|
20
21
|
- Public Key Pinning - Pin certificate fingerprints in the browser to prevent man-in-the-middle attacks due to compromised Certificate Authorities. [Public Key Pinning Specification](https://tools.ietf.org/html/rfc7469)
|
21
|
-
- Expect-CT - Only use certificates that are present in the certificate transparency logs. [Expect-CT draft specification](https://datatracker.ietf.org/doc/draft-stark-expect-ct/).
|
22
22
|
- Clear-Site-Data - Clearing browser data for origin. [Clear-Site-Data specification](https://w3c.github.io/webappsec-clear-site-data/).
|
23
23
|
|
24
24
|
It can also mark all http cookies with the Secure, HttpOnly and SameSite attributes (when configured to do so).
|
@@ -77,14 +77,8 @@ SecureHeaders::Configuration.default do |config|
|
|
77
77
|
"storage",
|
78
78
|
"executionContexts"
|
79
79
|
]
|
80
|
-
config.expect_certificate_transparency = {
|
81
|
-
enforce: false,
|
82
|
-
max_age: 1.day.to_i,
|
83
|
-
report_uri: "https://report-uri.io/example-ct"
|
84
|
-
}
|
85
80
|
config.csp = {
|
86
|
-
# "meta" values. these will
|
87
|
-
# report_only: true, # default: false [DEPRECATED from 3.5.0: instead, configure csp_report_only]
|
81
|
+
# "meta" values. these will shape the header, but the values are not included in the header.
|
88
82
|
preserve_schemes: true, # default: false. Schemes are removed from host sources to save bytes and discourage mixed content.
|
89
83
|
|
90
84
|
# directive values: these values will directly translate into source directives
|
@@ -103,7 +97,6 @@ SecureHeaders::Configuration.default do |config|
|
|
103
97
|
plugin_types: %w(application/x-shockwave-flash),
|
104
98
|
script_src: %w('self'),
|
105
99
|
style_src: %w('unsafe-inline'),
|
106
|
-
worker_src: %w('self'),
|
107
100
|
upgrade_insecure_requests: true, # see https://www.w3.org/TR/upgrade-insecure-requests/
|
108
101
|
report_uri: %w(https://report-uri.io/example-csp)
|
109
102
|
}
|
@@ -139,20 +132,6 @@ X-Permitted-Cross-Domain-Policies: none
|
|
139
132
|
X-Xss-Protection: 1; mode=block
|
140
133
|
```
|
141
134
|
|
142
|
-
### Default CSP
|
143
|
-
|
144
|
-
By default, the above CSP will be applied to all requests. If you **only** want to set a Report-Only header, opt-out of the default enforced header for clarity. The configuration will assume that if you only supply `csp_report_only` that you intended to opt-out of `csp` but that's for the sake of backwards compatibility and it will be removed in the future.
|
145
|
-
|
146
|
-
```ruby
|
147
|
-
Configuration.default do |config|
|
148
|
-
config.csp = SecureHeaders::OPT_OUT # If this line is omitted, we will assume you meant to opt out.
|
149
|
-
config.csp_report_only = {
|
150
|
-
default_src: %w('self')
|
151
|
-
}
|
152
|
-
end
|
153
|
-
```
|
154
|
-
|
155
|
-
|
156
135
|
## Similar libraries
|
157
136
|
|
158
137
|
* Rack [rack-secure_headers](https://github.com/frodsan/rack-secure_headers)
|
data/Rakefile
CHANGED
@@ -1,28 +1,32 @@
|
|
1
1
|
#!/usr/bin/env rake
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
2
|
+
# frozen_string_literal: true
|
3
|
+
require "bundler/gem_tasks"
|
4
|
+
require "rspec/core/rake_task"
|
5
|
+
require "net/http"
|
6
|
+
require "net/https"
|
6
7
|
|
7
|
-
|
8
|
-
RSpec::Core::RakeTask.new do |t|
|
9
|
-
t.verbose = false
|
10
|
-
t.rspec_opts = "--format progress"
|
11
|
-
end
|
12
|
-
|
13
|
-
task default: :spec
|
8
|
+
RSpec::Core::RakeTask.new
|
14
9
|
|
15
10
|
begin
|
16
|
-
require
|
11
|
+
require "rdoc/task"
|
17
12
|
rescue LoadError
|
18
|
-
require
|
19
|
-
require
|
13
|
+
require "rdoc/rdoc"
|
14
|
+
require "rake/rdoctask"
|
20
15
|
RDoc::Task = Rake::RDocTask
|
21
16
|
end
|
22
17
|
|
18
|
+
begin
|
19
|
+
require "rubocop/rake_task"
|
20
|
+
RuboCop::RakeTask.new
|
21
|
+
rescue LoadError
|
22
|
+
task(:rubocop) { $stderr.puts "RuboCop is disabled" }
|
23
|
+
end
|
24
|
+
|
23
25
|
RDoc::Task.new(:rdoc) do |rdoc|
|
24
|
-
rdoc.rdoc_dir =
|
25
|
-
rdoc.title =
|
26
|
-
rdoc.options <<
|
27
|
-
rdoc.rdoc_files.include(
|
26
|
+
rdoc.rdoc_dir = "rdoc"
|
27
|
+
rdoc.title = "SecureHeaders"
|
28
|
+
rdoc.options << "--line-numbers"
|
29
|
+
rdoc.rdoc_files.include("lib/**/*.rb")
|
28
30
|
end
|
31
|
+
|
32
|
+
task default: [:spec, :rubocop]
|
data/docs/cookies.md
CHANGED
@@ -4,14 +4,28 @@ SecureHeaders supports `Secure`, `HttpOnly` and [`SameSite`](https://tools.ietf.
|
|
4
4
|
|
5
5
|
__Note__: Regardless of the configuration specified, Secure cookies are only enabled for HTTPS requests.
|
6
6
|
|
7
|
+
#### Defaults
|
8
|
+
|
9
|
+
By default, all cookies will get both `Secure`, `HttpOnly`, and `SameSite=Lax`.
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
config.cookies = {
|
13
|
+
secure: true, # defaults to true but will be a no op on non-HTTPS requests
|
14
|
+
httponly: true, # defaults to true
|
15
|
+
samesite: { # defaults to set `SameSite=Lax`
|
16
|
+
lax: true
|
17
|
+
}
|
18
|
+
}
|
19
|
+
```
|
20
|
+
|
7
21
|
#### Boolean-based configuration
|
8
22
|
|
9
|
-
Boolean-based configuration is intended to globally enable or disable a specific cookie attribute.
|
23
|
+
Boolean-based configuration is intended to globally enable or disable a specific cookie attribute. *Note: As of 4.0, you must use OPT_OUT rather than false to opt out of the defaults.*
|
10
24
|
|
11
25
|
```ruby
|
12
26
|
config.cookies = {
|
13
27
|
secure: true, # mark all cookies as Secure
|
14
|
-
httponly:
|
28
|
+
httponly: OPT_OUT, # do not mark any cookies as HttpOnly
|
15
29
|
}
|
16
30
|
```
|
17
31
|
|
@@ -38,14 +52,13 @@ config.cookies = {
|
|
38
52
|
}
|
39
53
|
```
|
40
54
|
|
41
|
-
`Strict
|
55
|
+
`Strict` and `Lax` enforcement modes can also be specified using a Hash.
|
42
56
|
|
43
57
|
```ruby
|
44
58
|
config.cookies = {
|
45
59
|
samesite: {
|
46
60
|
strict: { only: ['_rails_session'] },
|
47
|
-
lax: { only: ['_guest'] }
|
48
|
-
none: { only: ['_tracking'] },
|
61
|
+
lax: { only: ['_guest'] }
|
49
62
|
}
|
50
63
|
}
|
51
64
|
```
|
data/lib/secure_headers.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require "secure_headers/configuration"
|
2
3
|
require "secure_headers/hash_helper"
|
3
4
|
require "secure_headers/headers/cookie"
|
@@ -11,7 +12,6 @@ require "secure_headers/headers/x_download_options"
|
|
11
12
|
require "secure_headers/headers/x_permitted_cross_domain_policies"
|
12
13
|
require "secure_headers/headers/referrer_policy"
|
13
14
|
require "secure_headers/headers/clear_site_data"
|
14
|
-
require "secure_headers/headers/expect_certificate_transparency"
|
15
15
|
require "secure_headers/middleware"
|
16
16
|
require "secure_headers/railtie"
|
17
17
|
require "secure_headers/view_helper"
|
@@ -52,7 +52,6 @@ module SecureHeaders
|
|
52
52
|
CSP = ContentSecurityPolicy
|
53
53
|
|
54
54
|
ALL_HEADER_CLASSES = [
|
55
|
-
ExpectCertificateTransparency,
|
56
55
|
ClearSiteData,
|
57
56
|
ContentSecurityPolicyConfig,
|
58
57
|
ContentSecurityPolicyReportOnlyConfig,
|
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "yaml"
|
2
3
|
|
3
4
|
module SecureHeaders
|
4
5
|
class Configuration
|
@@ -116,7 +117,7 @@ module SecureHeaders
|
|
116
117
|
|
117
118
|
attr_writer :hsts, :x_frame_options, :x_content_type_options,
|
118
119
|
:x_xss_protection, :x_download_options, :x_permitted_cross_domain_policies,
|
119
|
-
:referrer_policy, :clear_site_data
|
120
|
+
:referrer_policy, :clear_site_data
|
120
121
|
|
121
122
|
attr_reader :cached_headers, :csp, :cookies, :csp_report_only, :hpkp, :hpkp_report_host
|
122
123
|
|
@@ -143,7 +144,6 @@ module SecureHeaders
|
|
143
144
|
@x_frame_options = nil
|
144
145
|
@x_permitted_cross_domain_policies = nil
|
145
146
|
@x_xss_protection = nil
|
146
|
-
@expect_certificate_transparency = nil
|
147
147
|
|
148
148
|
self.hpkp = OPT_OUT
|
149
149
|
self.referrer_policy = OPT_OUT
|
@@ -169,7 +169,6 @@ module SecureHeaders
|
|
169
169
|
copy.x_download_options = @x_download_options
|
170
170
|
copy.x_permitted_cross_domain_policies = @x_permitted_cross_domain_policies
|
171
171
|
copy.clear_site_data = @clear_site_data
|
172
|
-
copy.expect_certificate_transparency = @expect_certificate_transparency
|
173
172
|
copy.referrer_policy = @referrer_policy
|
174
173
|
copy.hpkp = @hpkp
|
175
174
|
copy.hpkp_report_host = @hpkp_report_host
|
@@ -202,14 +201,12 @@ module SecureHeaders
|
|
202
201
|
XDownloadOptions.validate_config!(@x_download_options)
|
203
202
|
XPermittedCrossDomainPolicies.validate_config!(@x_permitted_cross_domain_policies)
|
204
203
|
ClearSiteData.validate_config!(@clear_site_data)
|
205
|
-
ExpectCertificateTransparency.validate_config!(@expect_certificate_transparency)
|
206
204
|
PublicKeyPins.validate_config!(@hpkp)
|
207
205
|
Cookie.validate_config!(@cookies)
|
208
206
|
end
|
209
207
|
|
210
208
|
def secure_cookies=(secure_cookies)
|
211
|
-
|
212
|
-
@cookies = (@cookies || {}).merge(secure: secure_cookies)
|
209
|
+
raise ArgumentError, "#{Kernel.caller.first}: `#secure_cookies=` is no longer supported. Please use `#cookies=` to configure secure cookies instead."
|
213
210
|
end
|
214
211
|
|
215
212
|
def csp=(new_csp)
|
@@ -217,10 +214,8 @@ module SecureHeaders
|
|
217
214
|
@csp = new_csp.dup
|
218
215
|
else
|
219
216
|
if new_csp[:report_only]
|
220
|
-
#
|
221
|
-
|
222
|
-
@csp = OPT_OUT
|
223
|
-
self.csp_report_only = new_csp
|
217
|
+
# invalid configuration implies that CSPRO should be set, CSP should not - so opt out
|
218
|
+
raise ArgumentError, "#{Kernel.caller.first}: `#csp=` was supplied a config with report_only: true. Use #csp_report_only="
|
224
219
|
else
|
225
220
|
@csp = ContentSecurityPolicyConfig.new(new_csp)
|
226
221
|
end
|
@@ -247,11 +242,6 @@ module SecureHeaders
|
|
247
242
|
end
|
248
243
|
end
|
249
244
|
end
|
250
|
-
|
251
|
-
if !@csp_report_only.opt_out? && @csp.to_h == ContentSecurityPolicyConfig::DEFAULT
|
252
|
-
Kernel.warn "#{Kernel.caller.first}: [DEPRECATION] `#csp_report_only=` was configured before `#csp=`. It is assumed you intended to opt out of `#csp=` so be sure to add `config.csp = SecureHeaders::OPT_OUT` to your config. Ensure that #csp_report_only is configured after #csp="
|
253
|
-
@csp = OPT_OUT
|
254
|
-
end
|
255
245
|
end
|
256
246
|
|
257
247
|
protected
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module SecureHeaders
|
2
3
|
class ClearSiteDataConfigError < StandardError; end
|
3
4
|
class ClearSiteData
|
@@ -16,7 +17,7 @@ module SecureHeaders
|
|
16
17
|
# Public: make an Clear-Site-Data header name, value pair
|
17
18
|
#
|
18
19
|
# Returns nil if not configured, returns header name and value if configured.
|
19
|
-
def make_header(config=nil)
|
20
|
+
def make_header(config = nil)
|
20
21
|
case config
|
21
22
|
when nil, OPT_OUT, []
|
22
23
|
# noop
|
@@ -1,6 +1,7 @@
|
|
1
|
-
|
2
|
-
require_relative
|
3
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative "policy_management"
|
3
|
+
require_relative "content_security_policy_config"
|
4
|
+
require "useragent"
|
4
5
|
|
5
6
|
module SecureHeaders
|
6
7
|
class ContentSecurityPolicy
|
@@ -54,18 +55,12 @@ module SecureHeaders
|
|
54
55
|
|
55
56
|
private
|
56
57
|
|
57
|
-
# frame-src is deprecated, child-src is being implemented. They are
|
58
|
-
# very similar and in most cases, the same value can be used for both.
|
59
58
|
def normalize_child_frame_src
|
60
59
|
if @config.frame_src && @config.child_src && @config.frame_src != @config.child_src
|
61
|
-
|
60
|
+
raise ArgumentError, "#{Kernel.caller.first}: both :child_src and :frame_src supplied and do not match. This can lead to inconsistent behavior across browsers."
|
62
61
|
end
|
63
62
|
|
64
|
-
|
65
|
-
@config.child_src || @config.frame_src
|
66
|
-
else
|
67
|
-
@config.frame_src || @config.child_src
|
68
|
-
end
|
63
|
+
@config.frame_src || @config.child_src
|
69
64
|
end
|
70
65
|
|
71
66
|
# Private: converts the config object into a string representing a policy.
|
@@ -80,55 +75,20 @@ module SecureHeaders
|
|
80
75
|
case DIRECTIVE_VALUE_TYPES[directive_name]
|
81
76
|
when :boolean
|
82
77
|
symbol_to_hyphen_case(directive_name) if @config.directive_value(directive_name)
|
83
|
-
when :
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
when :source_list
|
88
|
-
build_source_list_directive(directive_name)
|
78
|
+
when :string
|
79
|
+
[symbol_to_hyphen_case(directive_name), @config.directive_value(directive_name)].join(" ")
|
80
|
+
else
|
81
|
+
build_directive(directive_name)
|
89
82
|
end
|
90
83
|
end.compact.join("; ")
|
91
84
|
end
|
92
85
|
|
93
|
-
def build_sandbox_list_directive(directive)
|
94
|
-
return unless sandbox_list = @config.directive_value(directive)
|
95
|
-
max_strict_policy = case sandbox_list
|
96
|
-
when Array
|
97
|
-
sandbox_list.empty?
|
98
|
-
when true
|
99
|
-
true
|
100
|
-
else
|
101
|
-
false
|
102
|
-
end
|
103
|
-
|
104
|
-
# A maximally strict sandbox policy is just the `sandbox` directive,
|
105
|
-
# whith no configuraiton values.
|
106
|
-
if max_strict_policy
|
107
|
-
symbol_to_hyphen_case(directive)
|
108
|
-
elsif sandbox_list && sandbox_list.any?
|
109
|
-
[
|
110
|
-
symbol_to_hyphen_case(directive),
|
111
|
-
sandbox_list.uniq
|
112
|
-
].join(" ")
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
def build_media_type_list_directive(directive)
|
117
|
-
return unless media_type_list = @config.directive_value(directive)
|
118
|
-
if media_type_list && media_type_list.any?
|
119
|
-
[
|
120
|
-
symbol_to_hyphen_case(directive),
|
121
|
-
media_type_list.uniq
|
122
|
-
].join(" ")
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
86
|
# Private: builds a string that represents one directive in a minified form.
|
127
87
|
#
|
128
88
|
# directive_name - a symbol representing the various ALL_DIRECTIVES
|
129
89
|
#
|
130
90
|
# Returns a string representing a directive.
|
131
|
-
def
|
91
|
+
def build_directive(directive)
|
132
92
|
source_list = case directive
|
133
93
|
when :child_src
|
134
94
|
if supported_directives.include?(:child_src)
|
@@ -142,14 +102,8 @@ module SecureHeaders
|
|
142
102
|
@config.directive_value(directive)
|
143
103
|
end
|
144
104
|
return unless source_list && source_list.any?
|
145
|
-
normalized_source_list = minify_source_list(directive, source_list)
|
146
|
-
|
147
|
-
if normalized_source_list =~ /(\n|;)/
|
148
|
-
Kernel.warn("#{directive} contains a #{$1} in #{normalized_source_list.inspect} which will raise an error in future versions. It has been replaced with a blank space.")
|
149
|
-
end
|
150
|
-
escaped_source_list = normalized_source_list.gsub(/[\n;]/, " ")
|
151
|
-
|
152
|
-
[symbol_to_hyphen_case(directive), escaped_source_list].join(" ").strip
|
105
|
+
normalized_source_list = minify_source_list(directive, source_list)
|
106
|
+
[symbol_to_hyphen_case(directive), normalized_source_list].join(" ")
|
153
107
|
end
|
154
108
|
|
155
109
|
# If a directive contains *, all other values are omitted.
|
@@ -270,7 +224,7 @@ module SecureHeaders
|
|
270
224
|
end
|
271
225
|
|
272
226
|
def symbol_to_hyphen_case(sym)
|
273
|
-
sym.to_s.tr(
|
227
|
+
sym.to_s.tr("_", "-")
|
274
228
|
end
|
275
229
|
end
|
276
230
|
end
|