secure_headers 3.0.3 → 3.2.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 +4 -4
- data/.gitignore +0 -9
- data/.travis.yml +13 -5
- data/CHANGELOG.md +144 -0
- data/Gemfile +5 -2
- data/README.md +152 -61
- data/lib/secure_headers/configuration.rb +109 -54
- data/lib/secure_headers/hash_helper.rb +10 -0
- data/lib/secure_headers/headers/content_security_policy.rb +31 -309
- data/lib/secure_headers/headers/cookie.rb +126 -0
- data/lib/secure_headers/headers/policy_management.rb +320 -0
- data/lib/secure_headers/headers/x_content_type_options.rb +1 -1
- data/lib/secure_headers/middleware.rb +37 -0
- data/lib/secure_headers/railtie.rb +5 -1
- data/lib/secure_headers/utils/cookies_config.rb +94 -0
- data/lib/secure_headers/view_helper.rb +64 -0
- data/lib/secure_headers.rb +39 -63
- data/lib/tasks/tasks.rake +81 -0
- data/secure_headers.gemspec +1 -1
- data/spec/lib/secure_headers/configuration_spec.rb +18 -4
- data/spec/lib/secure_headers/headers/content_security_policy_spec.rb +0 -175
- data/spec/lib/secure_headers/headers/cookie_spec.rb +164 -0
- data/spec/lib/secure_headers/headers/policy_management_spec.rb +190 -0
- data/spec/lib/secure_headers/headers/strict_transport_security_spec.rb +1 -1
- data/spec/lib/secure_headers/middleware_spec.rb +59 -7
- data/spec/lib/secure_headers/view_helpers_spec.rb +125 -0
- data/spec/lib/secure_headers_spec.rb +119 -42
- data/spec/spec_helper.rb +16 -1
- data/upgrading-to-3-0.md +1 -0
- metadata +13 -4
- data/lib/secure_headers/padrino.rb +0 -13
- data/travis.sh +0 -10
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a02f16867ec55f8c168ace664cc63d760785256f
|
|
4
|
+
data.tar.gz: db54c113af8919984c8f382b957834f38210cf3e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6d9ddcb98a8c646d4e7a8cdb79bf3d8638cae4cb230ff268660e8eab7000fba99bb65e126ce55b3ff5f2a0346013fcf8b769dab4db697c82ab4461d444d0e2bd
|
|
7
|
+
data.tar.gz: b63c79ac3e9b37a4cff698f979f1ca6fd7e92567e35b1f9026be2e68a205e5badff302d512938a4d36517e8ec5b752d4833082e1b733ff73916fbf0b326641aa
|
data/.gitignore
CHANGED
|
@@ -6,17 +6,8 @@
|
|
|
6
6
|
.yardoc
|
|
7
7
|
*.log
|
|
8
8
|
Gemfile.lock
|
|
9
|
-
InstalledFiles
|
|
10
9
|
_yardoc
|
|
11
10
|
coverage
|
|
12
|
-
doc/
|
|
13
|
-
lib/bundler/man
|
|
14
11
|
pkg
|
|
15
12
|
rdoc
|
|
16
13
|
spec/reports
|
|
17
|
-
test/tmp
|
|
18
|
-
test/version_tmp
|
|
19
|
-
*tmp
|
|
20
|
-
*.sqlite3
|
|
21
|
-
fixtures/rails_3_2_12_no_init/log
|
|
22
|
-
fixtures/rails_3_2_12/log
|
data/.travis.yml
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
language: ruby
|
|
2
2
|
|
|
3
3
|
rvm:
|
|
4
|
-
-
|
|
5
|
-
-
|
|
6
|
-
-
|
|
7
|
-
-
|
|
8
|
-
-
|
|
4
|
+
- ruby-head
|
|
5
|
+
- 2.2
|
|
6
|
+
- 2.1
|
|
7
|
+
- 2.0.0
|
|
8
|
+
- 1.9.3
|
|
9
|
+
- jruby-19mode
|
|
10
|
+
- jruby-head
|
|
11
|
+
|
|
12
|
+
matrix:
|
|
13
|
+
allow_failures:
|
|
14
|
+
- rvm: jruby-head
|
|
15
|
+
- rvm: ruby-head
|
|
9
16
|
|
|
10
17
|
before_install: gem update bundler
|
|
18
|
+
bundler_args: --without guard -j 3
|
|
11
19
|
|
|
12
20
|
sudo: false
|
|
13
21
|
cache: bundler
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,146 @@
|
|
|
1
|
+
## 3.2.0 Cookie settings and CSP hash sources
|
|
2
|
+
|
|
3
|
+
### Cookies
|
|
4
|
+
|
|
5
|
+
SecureHeaders supports `Secure`, `HttpOnly` and [`SameSite`](https://tools.ietf.org/html/draft-west-first-party-cookies-07) cookies. These can be defined in the form of a boolean, or as a Hash for more refined configuration.
|
|
6
|
+
|
|
7
|
+
__Note__: Regardless of the configuration specified, Secure cookies are only enabled for HTTPS requests.
|
|
8
|
+
|
|
9
|
+
#### Boolean-based configuration
|
|
10
|
+
|
|
11
|
+
Boolean-based configuration is intended to globally enable or disable a specific cookie attribute.
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
config.cookies = {
|
|
15
|
+
secure: true, # mark all cookies as Secure
|
|
16
|
+
httponly: false, # do not mark any cookies as HttpOnly
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
#### Hash-based configuration
|
|
21
|
+
|
|
22
|
+
Hash-based configuration allows for fine-grained control.
|
|
23
|
+
|
|
24
|
+
```ruby
|
|
25
|
+
config.cookies = {
|
|
26
|
+
secure: { except: ['_guest'] }, # mark all but the `_guest` cookie as Secure
|
|
27
|
+
httponly: { only: ['_rails_session'] }, # only mark the `_rails_session` cookie as HttpOnly
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
#### SameSite cookie configuration
|
|
32
|
+
|
|
33
|
+
SameSite cookies permit either `Strict` or `Lax` enforcement mode options.
|
|
34
|
+
|
|
35
|
+
```ruby
|
|
36
|
+
config.cookies = {
|
|
37
|
+
samesite: {
|
|
38
|
+
strict: true # mark all cookies as SameSite=Strict
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`Strict` and `Lax` enforcement modes can also be specified using a Hash.
|
|
44
|
+
|
|
45
|
+
```ruby
|
|
46
|
+
config.cookies = {
|
|
47
|
+
samesite: {
|
|
48
|
+
strict: { only: ['_rails_session'] },
|
|
49
|
+
lax: { only: ['_guest'] }
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
#### Hash
|
|
55
|
+
|
|
56
|
+
`script`/`style-src` hashes can be used to whitelist inline content that is static. This has the benefit of allowing inline content without opening up the possibility of dynamic javascript like you would with a `nonce`.
|
|
57
|
+
|
|
58
|
+
You can add hash sources directly to your policy :
|
|
59
|
+
|
|
60
|
+
```ruby
|
|
61
|
+
::SecureHeaders::Configuration.default do |config|
|
|
62
|
+
config.csp = {
|
|
63
|
+
default_src: %w('self')
|
|
64
|
+
|
|
65
|
+
# this is a made up value but browsers will show the expected hash in the console.
|
|
66
|
+
script_src: %w(sha256-123456)
|
|
67
|
+
}
|
|
68
|
+
end
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
You can also use the automated inline script detection/collection/computation of hash source values in your app.
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
rake secure_headers:generate_hashes
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
This will generate a file (`config/config/secure_headers_generated_hashes.yml` by default, you can override by setting `ENV["secure_headers_generated_hashes_file"]`) containing a mapping of file names with the array of hash values found on that page. When ActionView renders a given file, we check if there are any known hashes for that given file. If so, they are added as values to the header.
|
|
78
|
+
|
|
79
|
+
```yaml
|
|
80
|
+
---
|
|
81
|
+
scripts:
|
|
82
|
+
app/views/asdfs/index.html.erb:
|
|
83
|
+
- "'sha256-yktKiAsZWmc8WpOyhnmhQoDf9G2dAZvuBBC+V0LGQhg='"
|
|
84
|
+
styles:
|
|
85
|
+
app/views/asdfs/index.html.erb:
|
|
86
|
+
- "'sha256-SLp6LO3rrKDJwsG9uJUxZapb4Wp2Zhj6Bu3l+d9rnAY='"
|
|
87
|
+
- "'sha256-HSGHqlRoKmHAGTAJ2Rq0piXX4CnEbOl1ArNd6ejp2TE='"
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
##### Helpers
|
|
91
|
+
|
|
92
|
+
**This will not compute dynamic hashes** by design. The output of both helpers will be a plain `script`/`style` tag without modification and the known hashes for a given file will be added to `script-src`/`style-src` when `hashed_javascript_tag` and `hashed_style_tag` are used. You can use `raise_error_on_unrecognized_hash = true` to be extra paranoid that you have precomputed hash values for all of your inline content. By default, this will raise an error in non-production environments.
|
|
93
|
+
|
|
94
|
+
```erb
|
|
95
|
+
<%= hashed_style_tag do %>
|
|
96
|
+
body {
|
|
97
|
+
background-color: black;
|
|
98
|
+
}
|
|
99
|
+
<% end %>
|
|
100
|
+
|
|
101
|
+
<%= hashed_style_tag do %>
|
|
102
|
+
body {
|
|
103
|
+
font-size: 30px;
|
|
104
|
+
font-color: green;
|
|
105
|
+
}
|
|
106
|
+
<% end %>
|
|
107
|
+
|
|
108
|
+
<%= hashed_javascript_tag do %>
|
|
109
|
+
console.log(1)
|
|
110
|
+
<% end %>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
Content-Security-Policy: ...
|
|
115
|
+
script-src 'sha256-yktKiAsZWmc8WpOyhnmhQoDf9G2dAZvuBBC+V0LGQhg=' ... ;
|
|
116
|
+
style-src 'sha256-SLp6LO3rrKDJwsG9uJUxZapb4Wp2Zhj6Bu3l+d9rnAY=' 'sha256-HSGHqlRoKmHAGTAJ2Rq0piXX4CnEbOl1ArNd6ejp2TE=' ...;
|
|
117
|
+
|
|
118
|
+
## 3.1.2 Bug fix for regression
|
|
119
|
+
|
|
120
|
+
See https://github.com/twitter/secureheaders/pull/239
|
|
121
|
+
|
|
122
|
+
This meant that when header caches were regenerated upon calling `SecureHeaders.override(:name)` and using it with `use_secure_headers_override` would result in default values for anything other than CSP/HPKP.
|
|
123
|
+
|
|
124
|
+
## 3.1.1 Bug fix for regression
|
|
125
|
+
|
|
126
|
+
See https://github.com/twitter/secureheaders/pull/235
|
|
127
|
+
|
|
128
|
+
`idempotent_additions?` would return false when comparing `OPT_OUT` with `OPT_OUT`, causing `header_hash_for` to return a header cache with `{ nil => nil }` which cause the middleware to blow up when `{ nil => nil }` was merged into the rack header hash.
|
|
129
|
+
|
|
130
|
+
This is a regression in 3.1.0 only.
|
|
131
|
+
|
|
132
|
+
Now it returns true. I've added a test case to ensure that `header_hash_for` will never return such an element.
|
|
133
|
+
|
|
134
|
+
## 3.1.0 Adding secure cookie support
|
|
135
|
+
|
|
136
|
+
New feature: marking all cookies as secure. Added by @jmera in https://github.com/twitter/secureheaders/pull/231. In the future, we'll probably add the ability to whitelist individual cookies that should not be marked secure. PRs welcome.
|
|
137
|
+
|
|
138
|
+
Internal refactoring: In https://github.com/twitter/secureheaders/pull/232, we changed the way dynamic CSP is handled internally. The biggest benefit is that highly dynamic policies (which can happen with multiple `append/override` calls per request) are handled better:
|
|
139
|
+
|
|
140
|
+
1. Only the CSP header cache is busted when using a dynamic policy. All other headers are preserved and don't need to be generated. Dynamic X-Frame-Options changes modify the cache directly.
|
|
141
|
+
1. Idempotency checks for policy modifications are deferred until the end of the request lifecycle and only happen once, instead of per `append/override` call. The idempotency check itself is fairly expensive itself.
|
|
142
|
+
1. CSP header string is produced at most once per request.
|
|
143
|
+
|
|
1
144
|
## 3.0.3
|
|
2
145
|
|
|
3
146
|
Bug fix for handling policy merges where appending a non-default source value (report-uri, plugin-types, frame-ancestors, base-uri, and form-action) would be combined with the default-src value. Appending a directive that doesn't exist in the current policy combines the new value with `default-src` to mimic the actual behavior of the addition. However, this does not make sense for non-default-src values (a.k.a. "fetch directives") and can lead to unexpected behavior like a `report-uri` value of `*`. Previously, this config:
|
|
@@ -14,6 +157,7 @@ When appending:
|
|
|
14
157
|
{
|
|
15
158
|
report_uri => %w(https://report-uri.io/asdf)
|
|
16
159
|
}
|
|
160
|
+
```
|
|
17
161
|
|
|
18
162
|
Would result in `default-src *; report-uri *` which doesn't make any sense at all.
|
|
19
163
|
|
data/Gemfile
CHANGED
|
@@ -6,9 +6,12 @@ group :test do
|
|
|
6
6
|
gem "tins", "~> 1.6.0" # 1.7 requires ruby 2.0
|
|
7
7
|
gem "pry-nav"
|
|
8
8
|
gem "rack"
|
|
9
|
+
gem "rspec"
|
|
10
|
+
gem "coveralls"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
group :guard do
|
|
9
14
|
gem "guard-rspec", platforms: [:ruby_19, :ruby_20, :ruby_21, :ruby_22]
|
|
10
|
-
gem "rspec", ">= 3.1"
|
|
11
15
|
gem "growl"
|
|
12
16
|
gem "rb-fsevent"
|
|
13
|
-
gem "coveralls", platforms: [:ruby_19, :ruby_20, :ruby_21, :ruby_22]
|
|
14
17
|
end
|
data/README.md
CHANGED
|
@@ -15,6 +15,8 @@ The gem will automatically apply several headers that are related to security.
|
|
|
15
15
|
- 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)
|
|
16
16
|
- 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)
|
|
17
17
|
|
|
18
|
+
It can also mark all http cookies with the Secure, HttpOnly and SameSite attributes (when configured to do so).
|
|
19
|
+
|
|
18
20
|
`secure_headers` is a library with a global config, per request overrides, and rack middleware that enables you customize your application settings.
|
|
19
21
|
|
|
20
22
|
## Use
|
|
@@ -29,7 +31,14 @@ All `nil` values will fallback to their default values. `SecureHeaders::OPT_OUT`
|
|
|
29
31
|
|
|
30
32
|
```ruby
|
|
31
33
|
SecureHeaders::Configuration.default do |config|
|
|
32
|
-
config.
|
|
34
|
+
config.cookies = {
|
|
35
|
+
secure: true, # mark all cookies as "Secure"
|
|
36
|
+
httponly: true, # mark all cookies as "HttpOnly"
|
|
37
|
+
samesite: {
|
|
38
|
+
strict: true # mark all cookies as SameSite=Strict
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
config.hsts = "max-age=#{20.years.to_i}; includeSubdomains; preload"
|
|
33
42
|
config.x_frame_options = "DENY"
|
|
34
43
|
config.x_content_type_options = "nosniff"
|
|
35
44
|
config.x_xss_protection = "1; mode=block"
|
|
@@ -57,13 +66,13 @@ SecureHeaders::Configuration.default do |config|
|
|
|
57
66
|
plugin_types: %w(application/x-shockwave-flash),
|
|
58
67
|
block_all_mixed_content: true, # see [http://www.w3.org/TR/mixed-content/](http://www.w3.org/TR/mixed-content/)
|
|
59
68
|
upgrade_insecure_requests: true, # see https://www.w3.org/TR/upgrade-insecure-requests/
|
|
60
|
-
report_uri: %w(https://
|
|
69
|
+
report_uri: %w(https://report-uri.io/example-csp)
|
|
61
70
|
}
|
|
62
71
|
config.hpkp = {
|
|
63
72
|
report_only: false,
|
|
64
73
|
max_age: 60.days.to_i,
|
|
65
74
|
include_subdomains: true,
|
|
66
|
-
report_uri: "https://
|
|
75
|
+
report_uri: "https://report-uri.io/example-hpkp",
|
|
67
76
|
pins: [
|
|
68
77
|
{sha256: "abc"},
|
|
69
78
|
{sha256: "123"}
|
|
@@ -175,7 +184,7 @@ When manipulating content security policy, there are a few things to consider. T
|
|
|
175
184
|
|
|
176
185
|
#### Append to the policy with a directive other than `default_src`
|
|
177
186
|
|
|
178
|
-
The value of `default_src` is joined with the addition. Note the `https:` is carried over from the `default-src` config. If you do not want this, use `override_content_security_policy_directives` instead. To illustrate:
|
|
187
|
+
The value of `default_src` is joined with the addition if the it is a [fetch directive](https://w3c.github.io/webappsec-csp/#directives-fetch). Note the `https:` is carried over from the `default-src` config. If you do not want this, use `override_content_security_policy_directives` instead. To illustrate:
|
|
179
188
|
|
|
180
189
|
```ruby
|
|
181
190
|
::SecureHeaders::Configuration.default do |config|
|
|
@@ -192,24 +201,6 @@ Code | Result
|
|
|
192
201
|
|
|
193
202
|
#### Nonce
|
|
194
203
|
|
|
195
|
-
script/style-nonce can be used to whitelist inline content. To do this, call the `SecureHeaders.content_security_policy_nonce` then set the nonce attributes on the various tags.
|
|
196
|
-
|
|
197
|
-
Setting a nonce will also set 'unsafe-inline' for browsers that don't support nonces for backwards compatibility. 'unsafe-inline' is ignored if a nonce is present in a directive in compliant browsers.
|
|
198
|
-
|
|
199
|
-
```erb
|
|
200
|
-
<script nonce="<%= content_security_policy_nonce %>">
|
|
201
|
-
console.log("whitelisted, will execute")
|
|
202
|
-
</script>
|
|
203
|
-
|
|
204
|
-
<script nonce="lol">
|
|
205
|
-
console.log("won't execute, not whitelisted")
|
|
206
|
-
</script>
|
|
207
|
-
|
|
208
|
-
<script>
|
|
209
|
-
console.log("won't execute, not whitelisted")
|
|
210
|
-
</script>
|
|
211
|
-
```
|
|
212
|
-
|
|
213
204
|
You can use a view helper to automatically add nonces to script tags:
|
|
214
205
|
|
|
215
206
|
```erb
|
|
@@ -237,9 +228,93 @@ body {
|
|
|
237
228
|
</style>
|
|
238
229
|
```
|
|
239
230
|
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Content-Security-Policy: ...
|
|
234
|
+
script-src 'nonce-/jRAxuLJsDXAxqhNBB7gg7h55KETtDQBXe4ZL+xIXwI=' ...;
|
|
235
|
+
style-src 'nonce-/jRAxuLJsDXAxqhNBB7gg7h55KETtDQBXe4ZL+xIXwI=' ...;
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
`script`/`style-nonce` can be used to whitelist inline content. To do this, call the `content_security_policy_script_nonce` or `content_security_policy_style_nonce` then set the nonce attributes on the various tags.
|
|
239
|
+
|
|
240
|
+
```erb
|
|
241
|
+
<script nonce="<%= content_security_policy_script_nonce %>">
|
|
242
|
+
console.log("whitelisted, will execute")
|
|
243
|
+
</script>
|
|
244
|
+
|
|
245
|
+
<script nonce="lol">
|
|
246
|
+
console.log("won't execute, not whitelisted")
|
|
247
|
+
</script>
|
|
248
|
+
|
|
249
|
+
<script>
|
|
250
|
+
console.log("won't execute, not whitelisted")
|
|
251
|
+
</script>
|
|
252
|
+
```
|
|
253
|
+
|
|
240
254
|
#### Hash
|
|
241
255
|
|
|
242
|
-
|
|
256
|
+
`script`/`style-src` hashes can be used to whitelist inline content that is static. This has the benefit of allowing inline content without opening up the possibility of dynamic javascript like you would with a `nonce`.
|
|
257
|
+
|
|
258
|
+
You can add hash sources directly to your policy :
|
|
259
|
+
|
|
260
|
+
```ruby
|
|
261
|
+
::SecureHeaders::Configuration.default do |config|
|
|
262
|
+
config.csp = {
|
|
263
|
+
default_src: %w('self')
|
|
264
|
+
|
|
265
|
+
# this is a made up value but browsers will show the expected hash in the console.
|
|
266
|
+
script_src: %w(sha256-123456)
|
|
267
|
+
}
|
|
268
|
+
end
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
You can also use the automated inline script detection/collection/computation of hash source values in your app.
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
rake secure_headers:generate_hashes
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
This will generate a file (`config/config/secure_headers_generated_hashes.yml` by default, you can override by setting `ENV["secure_headers_generated_hashes_file"]`) containing a mapping of file names with the array of hash values found on that page. When ActionView renders a given file, we check if there are any known hashes for that given file. If so, they are added as values to the header.
|
|
278
|
+
|
|
279
|
+
```yaml
|
|
280
|
+
---
|
|
281
|
+
scripts:
|
|
282
|
+
app/views/asdfs/index.html.erb:
|
|
283
|
+
- "'sha256-yktKiAsZWmc8WpOyhnmhQoDf9G2dAZvuBBC+V0LGQhg='"
|
|
284
|
+
styles:
|
|
285
|
+
app/views/asdfs/index.html.erb:
|
|
286
|
+
- "'sha256-SLp6LO3rrKDJwsG9uJUxZapb4Wp2Zhj6Bu3l+d9rnAY='"
|
|
287
|
+
- "'sha256-HSGHqlRoKmHAGTAJ2Rq0piXX4CnEbOl1ArNd6ejp2TE='"
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
##### Helpers
|
|
291
|
+
|
|
292
|
+
**This will not compute dynamic hashes** by design. The output of both helpers will be a plain `script`/`style` tag without modification and the known hashes for a given file will be added to `script-src`/`style-src` when `hashed_javascript_tag` and `hashed_style_tag` are used. You can use `raise_error_on_unrecognized_hash = true` to be extra paranoid that you have precomputed hash values for all of your inline content. By default, this will raise an error in non-production environments.
|
|
293
|
+
|
|
294
|
+
```erb
|
|
295
|
+
<%= hashed_style_tag do %>
|
|
296
|
+
body {
|
|
297
|
+
background-color: black;
|
|
298
|
+
}
|
|
299
|
+
<% end %>
|
|
300
|
+
|
|
301
|
+
<%= hashed_style_tag do %>
|
|
302
|
+
body {
|
|
303
|
+
font-size: 30px;
|
|
304
|
+
font-color: green;
|
|
305
|
+
}
|
|
306
|
+
<% end %>
|
|
307
|
+
|
|
308
|
+
<%= hashed_javascript_tag do %>
|
|
309
|
+
console.log(1)
|
|
310
|
+
<% end %>
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
```
|
|
314
|
+
Content-Security-Policy: ...
|
|
315
|
+
script-src 'sha256-yktKiAsZWmc8WpOyhnmhQoDf9G2dAZvuBBC+V0LGQhg=' ... ;
|
|
316
|
+
style-src 'sha256-SLp6LO3rrKDJwsG9uJUxZapb4Wp2Zhj6Bu3l+d9rnAY=' 'sha256-HSGHqlRoKmHAGTAJ2Rq0piXX4CnEbOl1ArNd6ejp2TE=' ...;
|
|
317
|
+
```
|
|
243
318
|
|
|
244
319
|
### Public Key Pins
|
|
245
320
|
|
|
@@ -255,12 +330,63 @@ config.hpkp = {
|
|
|
255
330
|
{sha256: '73a2c64f9545172c1195efb6616ca5f7afd1df6f245407cafb90de3998a1c97f'}
|
|
256
331
|
],
|
|
257
332
|
report_only: true, # defaults to false (report-only mode)
|
|
258
|
-
report_uri: '
|
|
333
|
+
report_uri: 'https://report-uri.io/example-hpkp',
|
|
259
334
|
app_name: 'example',
|
|
260
335
|
tag_report_uri: true
|
|
261
336
|
}
|
|
262
337
|
```
|
|
263
338
|
|
|
339
|
+
### Cookies
|
|
340
|
+
|
|
341
|
+
SecureHeaders supports `Secure`, `HttpOnly` and [`SameSite`](https://tools.ietf.org/html/draft-west-first-party-cookies-07) cookies. These can be defined in the form of a boolean, or as a Hash for more refined configuration.
|
|
342
|
+
|
|
343
|
+
__Note__: Regardless of the configuration specified, Secure cookies are only enabled for HTTPS requests.
|
|
344
|
+
|
|
345
|
+
#### Boolean-based configuration
|
|
346
|
+
|
|
347
|
+
Boolean-based configuration is intended to globally enable or disable a specific cookie attribute.
|
|
348
|
+
|
|
349
|
+
```ruby
|
|
350
|
+
config.cookies = {
|
|
351
|
+
secure: true, # mark all cookies as Secure
|
|
352
|
+
httponly: false, # do not mark any cookies as HttpOnly
|
|
353
|
+
}
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
#### Hash-based configuration
|
|
357
|
+
|
|
358
|
+
Hash-based configuration allows for fine-grained control.
|
|
359
|
+
|
|
360
|
+
```ruby
|
|
361
|
+
config.cookies = {
|
|
362
|
+
secure: { except: ['_guest'] }, # mark all but the `_guest` cookie as Secure
|
|
363
|
+
httponly: { only: ['_rails_session'] }, # only mark the `_rails_session` cookie as HttpOnly
|
|
364
|
+
}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
#### SameSite cookie configuration
|
|
368
|
+
|
|
369
|
+
SameSite cookies permit either `Strict` or `Lax` enforcement mode options.
|
|
370
|
+
|
|
371
|
+
```ruby
|
|
372
|
+
config.cookies = {
|
|
373
|
+
samesite: {
|
|
374
|
+
strict: true # mark all cookies as SameSite=Strict
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
`Strict` and `Lax` enforcement modes can also be specified using a Hash.
|
|
380
|
+
|
|
381
|
+
```ruby
|
|
382
|
+
config.cookies = {
|
|
383
|
+
samesite: {
|
|
384
|
+
strict: { only: ['_rails_session'] },
|
|
385
|
+
lax: { only: ['_guest'] }
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
```
|
|
389
|
+
|
|
264
390
|
### Using with Sinatra
|
|
265
391
|
|
|
266
392
|
Here's an example using SecureHeaders for Sinatra applications:
|
|
@@ -287,43 +413,6 @@ class Donkey < Sinatra::Application
|
|
|
287
413
|
end
|
|
288
414
|
```
|
|
289
415
|
|
|
290
|
-
### Using with Padrino
|
|
291
|
-
|
|
292
|
-
You can use SecureHeaders for Padrino applications as well:
|
|
293
|
-
|
|
294
|
-
In your `Gemfile`:
|
|
295
|
-
|
|
296
|
-
```ruby
|
|
297
|
-
gem "secure_headers", require: 'secure_headers'
|
|
298
|
-
```
|
|
299
|
-
|
|
300
|
-
then in your `app.rb` file you can:
|
|
301
|
-
|
|
302
|
-
```ruby
|
|
303
|
-
Padrino.use(SecureHeaders::Middleware)
|
|
304
|
-
require 'secure_headers/padrino'
|
|
305
|
-
|
|
306
|
-
module Web
|
|
307
|
-
class App < Padrino::Application
|
|
308
|
-
register SecureHeaders::Padrino
|
|
309
|
-
|
|
310
|
-
get '/' do
|
|
311
|
-
render 'index'
|
|
312
|
-
end
|
|
313
|
-
end
|
|
314
|
-
end
|
|
315
|
-
```
|
|
316
|
-
|
|
317
|
-
and in `config/boot.rb`:
|
|
318
|
-
|
|
319
|
-
```ruby
|
|
320
|
-
def before_load
|
|
321
|
-
SecureHeaders::Configuration.default do |config|
|
|
322
|
-
...
|
|
323
|
-
end
|
|
324
|
-
end
|
|
325
|
-
```
|
|
326
|
-
|
|
327
416
|
## Similar libraries
|
|
328
417
|
|
|
329
418
|
* Rack [rack-secure_headers](https://github.com/frodsan/rack-secure_headers)
|
|
@@ -334,6 +423,8 @@ end
|
|
|
334
423
|
* Python - [django-csp](https://github.com/mozilla/django-csp) + [commonware](https://github.com/jsocol/commonware/); [django-security](https://github.com/sdelements/django-security)
|
|
335
424
|
* Go - [secureheader](https://github.com/kr/secureheader)
|
|
336
425
|
* Elixir [secure_headers](https://github.com/anotherhale/secure_headers)
|
|
426
|
+
* Dropwizard [dropwizard-web-security](https://github.com/palantir/dropwizard-web-security)
|
|
427
|
+
* Ember.js [ember-cli-content-security-policy](https://github.com/rwjblue/ember-cli-content-security-policy/)
|
|
337
428
|
|
|
338
429
|
## License
|
|
339
430
|
|