secure_headers 3.3.2 → 3.4.0
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 +4 -4
- data/.github/ISSUE_TEMPLATE.md +41 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +20 -0
- data/CHANGELOG.md +14 -0
- data/Gemfile +2 -1
- data/README.md +8 -9
- data/lib/secure_headers/configuration.rb +2 -2
- data/lib/secure_headers/headers/content_security_policy.rb +33 -3
- data/lib/secure_headers/headers/policy_management.rb +14 -0
- data/lib/secure_headers/view_helper.rb +3 -5
- data/secure_headers.gemspec +1 -1
- data/spec/lib/secure_headers/headers/content_security_policy_spec.rb +37 -11
- data/spec/lib/secure_headers/headers/policy_management_spec.rb +2 -2
- data/spec/lib/secure_headers_spec.rb +3 -2
- data/spec/spec_helper.rb +2 -1
- data/upgrading-to-3-0.md +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 88233251c7a26e1269f77957d56823619e3d9d11
|
4
|
+
data.tar.gz: 8e9c0e69fcca0298ee52223d587134f5a8df062f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f421d0d58eb9b5a7b22fd13932644c2c3868e0294886cbf5250127e8807fa20dec95717219e0a82ce59f49f376b32e17b97b77c7e011d2e2d1633162c1297bbc
|
7
|
+
data.tar.gz: ae63cbdd588bf6c31e531bfec5480e022a5df96c8ee2cc4c824d1e869f64df2a44073d795cc6d5e7ffeca6d6369f0d2e33f202ce8ceda04d274849e95789ff43
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# Feature Requests
|
2
|
+
|
3
|
+
## Adding a new header
|
4
|
+
|
5
|
+
Generally, adding a new header is always OK.
|
6
|
+
|
7
|
+
* Is the header supported by any user agent? If so, which?
|
8
|
+
* What does it do?
|
9
|
+
* What are the valid values for the header?
|
10
|
+
* Where does the specification live?
|
11
|
+
|
12
|
+
## Adding a new CSP directive
|
13
|
+
|
14
|
+
* Is the directive supported by any user agent? If so, which?
|
15
|
+
* What does it do?
|
16
|
+
* What are the valid values for the directive?
|
17
|
+
|
18
|
+
---
|
19
|
+
|
20
|
+
# Bugs
|
21
|
+
|
22
|
+
Console errors and deprecation warnings are considered bugs that should be addressed with more precise UA sniffing. Bugs caused by incorrect or invalid UA sniffing are also bugs.
|
23
|
+
|
24
|
+
### Expected outcome
|
25
|
+
|
26
|
+
Describe what you expected to happen
|
27
|
+
|
28
|
+
1. I configure CSP to do X
|
29
|
+
1. When I inspect the response headers, the CSP should have included X
|
30
|
+
|
31
|
+
### Actual outcome
|
32
|
+
|
33
|
+
1. The generated policy did not include X
|
34
|
+
|
35
|
+
### Config
|
36
|
+
|
37
|
+
Please provide the configuration (`SecureHeaders::Configuration.default`) you are using including any overrides (`SecureHeaders::Configuration.override`).
|
38
|
+
|
39
|
+
### Generated headers
|
40
|
+
|
41
|
+
Provide a sample response containing the headers
|
@@ -0,0 +1,20 @@
|
|
1
|
+
## All PRs:
|
2
|
+
|
3
|
+
* [ ] Has tests
|
4
|
+
* [ ] Documentation updated
|
5
|
+
|
6
|
+
## Adding a new header
|
7
|
+
|
8
|
+
Generally, adding a new header is always OK.
|
9
|
+
|
10
|
+
* Is the header supported by any user agent? If so, which?
|
11
|
+
* What does it do?
|
12
|
+
* What are the valid values for the header?
|
13
|
+
* Where does the specification live?
|
14
|
+
|
15
|
+
## Adding a new CSP directive
|
16
|
+
|
17
|
+
* Is the directive supported by any user agent? If so, which?
|
18
|
+
* What does it do?
|
19
|
+
* What are the valid values for the directive?
|
20
|
+
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
## 3.4.0 the frame-src/child-src transition for Firefox.
|
2
|
+
|
3
|
+
Handle the `child-src`/`frame-src` transition semi-intelligently across versions. I think the code best descibes the behavior here:
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
if supported_directives.include?(:child_src)
|
7
|
+
@config[:child_src] = @config[:child_src] || @config[:frame_src]
|
8
|
+
else
|
9
|
+
@config[:frame_src] = @config[:frame_src] || @config[:child_src]
|
10
|
+
end
|
11
|
+
```
|
12
|
+
|
13
|
+
Also, @koenpunt noticed that we were [loading view helpers](https://github.com/twitter/secureheaders/pull/272) in a way that Rails 5 did not like.
|
14
|
+
|
1
15
|
## 3.3.2 minor fix to silence warnings when using rake
|
2
16
|
|
3
17
|
[@dankohn](https://github.com/twitter/secureheaders/issues/257) was seeing "already initialized" errors in his output. This change conditionally defines the constants.
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -8,7 +8,7 @@
|
|
8
8
|
The gem will automatically apply several headers that are related to security. This includes:
|
9
9
|
- Content Security Policy (CSP) - Helps detect/prevent XSS, mixed-content, and other classes of attack. [CSP 2 Specification](http://www.w3.org/TR/CSP2/)
|
10
10
|
- 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)
|
11
|
-
- X-Frame-Options (XFO) - Prevents your content from being framed and potentially clickjacked. [X-Frame-Options
|
11
|
+
- X-Frame-Options (XFO) - Prevents your content from being framed and potentially clickjacked. [X-Frame-Options Specification](https://tools.ietf.org/html/rfc7034)
|
12
12
|
- X-XSS-Protection - [Cross site scripting heuristic filter for IE/Chrome](https://msdn.microsoft.com/en-us/library/dd565647\(v=vs.85\).aspx)
|
13
13
|
- X-Content-Type-Options - [Prevent content type sniffing](https://msdn.microsoft.com/library/gg622941\(v=vs.85\).aspx)
|
14
14
|
- X-Download-Options - [Prevent file downloads opening](https://msdn.microsoft.com/library/jj542450(v=vs.85).aspx)
|
@@ -53,20 +53,19 @@ SecureHeaders::Configuration.default do |config|
|
|
53
53
|
|
54
54
|
# directive values: these values will directly translate into source directives
|
55
55
|
default_src: %w(https: 'self'),
|
56
|
-
|
57
|
-
|
56
|
+
base_uri: %w('self'),
|
57
|
+
block_all_mixed_content: true, # see http://www.w3.org/TR/mixed-content/
|
58
|
+
child_src: %w('self'), # if child-src isn't supported, the value for frame-src will be set.
|
59
|
+
connect_src: %w(wss:),
|
58
60
|
font_src: %w('self' data:),
|
61
|
+
form_action: %w('self' github.com),
|
62
|
+
frame_ancestors: %w('none'),
|
59
63
|
img_src: %w(mycdn.com data:),
|
60
64
|
media_src: %w(utoob.com),
|
61
65
|
object_src: %w('self'),
|
66
|
+
plugin_types: %w(application/x-shockwave-flash),
|
62
67
|
script_src: %w('self'),
|
63
68
|
style_src: %w('unsafe-inline'),
|
64
|
-
base_uri: %w('self'),
|
65
|
-
child_src: %w('self'),
|
66
|
-
form_action: %w('self' github.com),
|
67
|
-
frame_ancestors: %w('none'),
|
68
|
-
plugin_types: %w(application/x-shockwave-flash),
|
69
|
-
block_all_mixed_content: true, # see http://www.w3.org/TR/mixed-content/
|
70
69
|
upgrade_insecure_requests: true, # see https://www.w3.org/TR/upgrade-insecure-requests/
|
71
70
|
report_uri: %w(https://report-uri.io/example-csp)
|
72
71
|
}
|
@@ -203,7 +203,7 @@ module SecureHeaders
|
|
203
203
|
raise IllegalPolicyModificationError, "You are attempting to modify CSP settings directly. Use dynamic_csp= instead."
|
204
204
|
end
|
205
205
|
|
206
|
-
@csp = new_csp
|
206
|
+
@csp = self.class.send(:deep_copy_if_hash, new_csp)
|
207
207
|
end
|
208
208
|
|
209
209
|
def cookies=(cookies)
|
@@ -215,7 +215,7 @@ module SecureHeaders
|
|
215
215
|
end
|
216
216
|
|
217
217
|
def hpkp=(hpkp)
|
218
|
-
@hpkp = hpkp
|
218
|
+
@hpkp = self.class.send(:deep_copy_if_hash, hpkp)
|
219
219
|
end
|
220
220
|
|
221
221
|
def hpkp_report_host=(hpkp_report_host)
|
@@ -1,18 +1,22 @@
|
|
1
1
|
require_relative 'policy_management'
|
2
|
+
require 'useragent'
|
2
3
|
|
3
4
|
module SecureHeaders
|
4
5
|
class ContentSecurityPolicyConfigError < StandardError; end
|
5
6
|
class ContentSecurityPolicy
|
6
7
|
include PolicyManagement
|
7
8
|
|
9
|
+
# constants to be used for version-specific UA sniffing
|
10
|
+
VERSION_46 = ::UserAgent::Version.new("46")
|
11
|
+
|
8
12
|
def initialize(config = nil, user_agent = OTHER)
|
9
|
-
config = Configuration.deep_copy
|
10
|
-
@config = config
|
13
|
+
@config = Configuration.send(:deep_copy, config || DEFAULT_CONFIG)
|
11
14
|
@parsed_ua = if user_agent.is_a?(UserAgent::Browsers::Base)
|
12
15
|
user_agent
|
13
16
|
else
|
14
17
|
UserAgent.parse(user_agent)
|
15
18
|
end
|
19
|
+
normalize_child_frame_src
|
16
20
|
@report_only = @config[:report_only]
|
17
21
|
@preserve_schemes = @config[:preserve_schemes]
|
18
22
|
@script_nonce = @config[:script_nonce]
|
@@ -42,6 +46,22 @@ module SecureHeaders
|
|
42
46
|
|
43
47
|
private
|
44
48
|
|
49
|
+
# frame-src is deprecated, child-src is being implemented. They are
|
50
|
+
# very similar and in most cases, the same value can be used for both.
|
51
|
+
def normalize_child_frame_src
|
52
|
+
if @config[:frame_src] && @config[:child_src] && @config[:frame_src] != @config[:child_src]
|
53
|
+
Kernel.warn("#{Kernel.caller.first}: [DEPRECATION] both :child_src and :frame_src supplied and do not match. This can lead to inconsistent behavior across browsers.")
|
54
|
+
elsif @config[:frame_src]
|
55
|
+
Kernel.warn("#{Kernel.caller.first}: [DEPRECATION] :frame_src is deprecated, use :child_src instead. Provided: #{@config[:frame_src]}.")
|
56
|
+
end
|
57
|
+
|
58
|
+
if supported_directives.include?(:child_src)
|
59
|
+
@config[:child_src] = @config[:child_src] || @config[:frame_src]
|
60
|
+
else
|
61
|
+
@config[:frame_src] = @config[:frame_src] || @config[:child_src]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
45
65
|
# Private: converts the config object into a string representing a policy.
|
46
66
|
# Places default-src at the first directive and report-uri as the last. All
|
47
67
|
# others are presented in alphabetical order.
|
@@ -162,9 +182,19 @@ module SecureHeaders
|
|
162
182
|
|
163
183
|
# Private: determine which directives are supported for the given user agent.
|
164
184
|
#
|
185
|
+
# Add UA-sniffing special casing here.
|
186
|
+
#
|
165
187
|
# Returns an array of symbols representing the directives.
|
166
188
|
def supported_directives
|
167
|
-
@supported_directives ||= VARIATIONS[@parsed_ua.browser]
|
189
|
+
@supported_directives ||= if VARIATIONS[@parsed_ua.browser]
|
190
|
+
if @parsed_ua.browser == "Firefox" && @parsed_ua.version >= VERSION_46
|
191
|
+
VARIATIONS["FirefoxTransitional"]
|
192
|
+
else
|
193
|
+
VARIATIONS[@parsed_ua.browser]
|
194
|
+
end
|
195
|
+
else
|
196
|
+
VARIATIONS[OTHER]
|
197
|
+
end
|
168
198
|
end
|
169
199
|
|
170
200
|
def nonces_supported?
|
@@ -100,10 +100,23 @@ module SecureHeaders
|
|
100
100
|
PLUGIN_TYPES
|
101
101
|
].freeze
|
102
102
|
|
103
|
+
FIREFOX_46_DEPRECATED_DIRECTIVES = [
|
104
|
+
FRAME_SRC
|
105
|
+
].freeze
|
106
|
+
|
107
|
+
FIREFOX_46_UNSUPPORTED_DIRECTIVES = [
|
108
|
+
BLOCK_ALL_MIXED_CONTENT,
|
109
|
+
PLUGIN_TYPES
|
110
|
+
].freeze
|
111
|
+
|
103
112
|
FIREFOX_DIRECTIVES = (
|
104
113
|
DIRECTIVES_2_0 + DIRECTIVES_DRAFT - FIREFOX_UNSUPPORTED_DIRECTIVES
|
105
114
|
).freeze
|
106
115
|
|
116
|
+
FIREFOX_46_DIRECTIVES = (
|
117
|
+
DIRECTIVES_2_0 + DIRECTIVES_DRAFT - FIREFOX_46_UNSUPPORTED_DIRECTIVES - FIREFOX_46_DEPRECATED_DIRECTIVES
|
118
|
+
).freeze
|
119
|
+
|
107
120
|
CHROME_DIRECTIVES = (
|
108
121
|
DIRECTIVES_2_0 + DIRECTIVES_DRAFT
|
109
122
|
).freeze
|
@@ -118,6 +131,7 @@ module SecureHeaders
|
|
118
131
|
"Chrome" => CHROME_DIRECTIVES,
|
119
132
|
"Opera" => CHROME_DIRECTIVES,
|
120
133
|
"Firefox" => FIREFOX_DIRECTIVES,
|
134
|
+
"FirefoxTransitional" => FIREFOX_46_DIRECTIVES,
|
121
135
|
"Safari" => SAFARI_DIRECTIVES,
|
122
136
|
"Edge" => EDGE_DIRECTIVES,
|
123
137
|
"Other" => CHROME_DIRECTIVES
|
@@ -108,8 +108,6 @@ module SecureHeaders
|
|
108
108
|
end
|
109
109
|
end
|
110
110
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
end
|
115
|
-
end
|
111
|
+
ActiveSupport.on_load :action_view do
|
112
|
+
include SecureHeaders::ViewHelpers
|
113
|
+
end if defined?(ActiveSupport)
|
data/secure_headers.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
Gem::Specification.new do |gem|
|
3
3
|
gem.name = "secure_headers"
|
4
|
-
gem.version = "3.
|
4
|
+
gem.version = "3.4.0"
|
5
5
|
gem.authors = ["Neil Matatall"]
|
6
6
|
gem.email = ["neil.matatall@gmail.com"]
|
7
7
|
gem.description = 'Security related headers all in one gem.'
|
@@ -24,7 +24,7 @@ module SecureHeaders
|
|
24
24
|
|
25
25
|
describe "#value" do
|
26
26
|
it "discards 'none' values if any other source expressions are present" do
|
27
|
-
csp = ContentSecurityPolicy.new(default_opts.merge(
|
27
|
+
csp = ContentSecurityPolicy.new(default_opts.merge(child_src: %w('self' 'none')))
|
28
28
|
expect(csp.value).not_to include("'none'")
|
29
29
|
end
|
30
30
|
|
@@ -86,42 +86,68 @@ module SecureHeaders
|
|
86
86
|
expect(csp.value).to eq("default-src example.org")
|
87
87
|
end
|
88
88
|
|
89
|
+
it "emits a warning when using frame-src" do
|
90
|
+
expect(Kernel).to receive(:warn).with(/:frame_src is deprecated, use :child_src instead./)
|
91
|
+
ContentSecurityPolicy.new(default_src: %w('self'), frame_src: %w('self')).value
|
92
|
+
end
|
93
|
+
|
94
|
+
it "emits a warning when child-src and frame-src are supplied but are not equal" do
|
95
|
+
expect(Kernel).to receive(:warn).with(/both :child_src and :frame_src supplied and do not match./)
|
96
|
+
ContentSecurityPolicy.new(default_src: %w('self'), child_src: %w(child-src.com), frame_src: %w(frame-src,com)).value
|
97
|
+
end
|
98
|
+
|
99
|
+
it "will still set inconsistent child/frame-src values to be less surprising" do
|
100
|
+
expect(Kernel).to receive(:warn).at_least(:once)
|
101
|
+
firefox = ContentSecurityPolicy.new({default_src: %w('self'), child_src: %w(child-src.com), frame_src: %w(frame-src,com)}, USER_AGENTS[:firefox]).value
|
102
|
+
firefox_transitional = ContentSecurityPolicy.new({default_src: %w('self'), child_src: %w(child-src.com), frame_src: %w(frame-src,com)}, USER_AGENTS[:firefox46]).value
|
103
|
+
expect(firefox).not_to eq(firefox_transitional)
|
104
|
+
expect(firefox).to match(/frame-src/)
|
105
|
+
expect(firefox).not_to match(/child-src/)
|
106
|
+
expect(firefox_transitional).to match(/child-src/)
|
107
|
+
expect(firefox_transitional).not_to match(/frame-src/)
|
108
|
+
end
|
109
|
+
|
89
110
|
context "browser sniffing" do
|
90
111
|
let (:complex_opts) do
|
91
|
-
ContentSecurityPolicy::ALL_DIRECTIVES.each_with_object({}) do |directive, hash|
|
92
|
-
hash[directive] =
|
112
|
+
(ContentSecurityPolicy::ALL_DIRECTIVES - [:frame_src]).each_with_object({}) do |directive, hash|
|
113
|
+
hash[directive] = ["#{directive.to_s.gsub("_", "-")}.com"]
|
93
114
|
end.merge({
|
94
115
|
block_all_mixed_content: true,
|
95
116
|
upgrade_insecure_requests: true,
|
96
117
|
reflected_xss: "block",
|
97
|
-
script_src: %w(
|
118
|
+
script_src: %w(script-src.com),
|
98
119
|
script_nonce: 123456
|
99
120
|
})
|
100
121
|
end
|
101
122
|
|
102
123
|
it "does not filter any directives for Chrome" do
|
103
124
|
policy = ContentSecurityPolicy.new(complex_opts, USER_AGENTS[:chrome])
|
104
|
-
expect(policy.value).to eq("default-src
|
125
|
+
expect(policy.value).to eq("default-src default-src.com; base-uri base-uri.com; block-all-mixed-content; child-src child-src.com; connect-src connect-src.com; font-src font-src.com; form-action form-action.com; frame-ancestors frame-ancestors.com; img-src img-src.com; media-src media-src.com; object-src object-src.com; plugin-types plugin-types.com; sandbox sandbox.com; script-src script-src.com 'nonce-123456'; style-src style-src.com; upgrade-insecure-requests; report-uri report-uri.com")
|
105
126
|
end
|
106
127
|
|
107
128
|
it "does not filter any directives for Opera" do
|
108
129
|
policy = ContentSecurityPolicy.new(complex_opts, USER_AGENTS[:opera])
|
109
|
-
expect(policy.value).to eq("default-src
|
130
|
+
expect(policy.value).to eq("default-src default-src.com; base-uri base-uri.com; block-all-mixed-content; child-src child-src.com; connect-src connect-src.com; font-src font-src.com; form-action form-action.com; frame-ancestors frame-ancestors.com; img-src img-src.com; media-src media-src.com; object-src object-src.com; plugin-types plugin-types.com; sandbox sandbox.com; script-src script-src.com 'nonce-123456'; style-src style-src.com; upgrade-insecure-requests; report-uri report-uri.com")
|
110
131
|
end
|
111
132
|
|
112
133
|
it "filters blocked-all-mixed-content, child-src, and plugin-types for firefox" do
|
113
134
|
policy = ContentSecurityPolicy.new(complex_opts, USER_AGENTS[:firefox])
|
114
|
-
expect(policy.value).to eq("default-src
|
135
|
+
expect(policy.value).to eq("default-src default-src.com; base-uri base-uri.com; connect-src connect-src.com; font-src font-src.com; form-action form-action.com; frame-ancestors frame-ancestors.com; frame-src child-src.com; img-src img-src.com; media-src media-src.com; object-src object-src.com; sandbox sandbox.com; script-src script-src.com 'nonce-123456'; style-src style-src.com; upgrade-insecure-requests; report-uri report-uri.com")
|
136
|
+
end
|
137
|
+
|
138
|
+
it "filters blocked-all-mixed-content, frame-src, and plugin-types for firefox 46 and higher" do
|
139
|
+
policy = ContentSecurityPolicy.new(complex_opts, USER_AGENTS[:firefox46])
|
140
|
+
expect(policy.value).to eq("default-src default-src.com; base-uri base-uri.com; child-src child-src.com; connect-src connect-src.com; font-src font-src.com; form-action form-action.com; frame-ancestors frame-ancestors.com; img-src img-src.com; media-src media-src.com; object-src object-src.com; sandbox sandbox.com; script-src script-src.com 'nonce-123456'; style-src style-src.com; upgrade-insecure-requests; report-uri report-uri.com")
|
115
141
|
end
|
116
142
|
|
117
|
-
it "adds 'unsafe-inline', filters base-uri, blocked-all-mixed-content, upgrade-insecure-requests, child-src, form-action, frame-ancestors, nonce sources, hash sources, and plugin-types for Edge" do
|
143
|
+
it "child-src value is copied to frame-src, adds 'unsafe-inline', filters base-uri, blocked-all-mixed-content, upgrade-insecure-requests, child-src, form-action, frame-ancestors, nonce sources, hash sources, and plugin-types for Edge" do
|
118
144
|
policy = ContentSecurityPolicy.new(complex_opts, USER_AGENTS[:edge])
|
119
|
-
expect(policy.value).to eq("default-src
|
145
|
+
expect(policy.value).to eq("default-src default-src.com; connect-src connect-src.com; font-src font-src.com; frame-src child-src.com; img-src img-src.com; media-src media-src.com; object-src object-src.com; sandbox sandbox.com; script-src script-src.com 'unsafe-inline'; style-src style-src.com; report-uri report-uri.com")
|
120
146
|
end
|
121
147
|
|
122
|
-
it "adds 'unsafe-inline', filters base-uri, blocked-all-mixed-content, upgrade-insecure-requests, child-src, form-action, frame-ancestors, nonce sources, hash sources, and plugin-types for safari" do
|
148
|
+
it "child-src value is copied to frame-src, adds 'unsafe-inline', filters base-uri, blocked-all-mixed-content, upgrade-insecure-requests, child-src, form-action, frame-ancestors, nonce sources, hash sources, and plugin-types for safari" do
|
123
149
|
policy = ContentSecurityPolicy.new(complex_opts, USER_AGENTS[:safari6])
|
124
|
-
expect(policy.value).to eq("default-src
|
150
|
+
expect(policy.value).to eq("default-src default-src.com; connect-src connect-src.com; font-src font-src.com; frame-src child-src.com; img-src img-src.com; media-src media-src.com; object-src object-src.com; sandbox sandbox.com; script-src script-src.com 'unsafe-inline'; style-src style-src.com; report-uri report-uri.com")
|
125
151
|
end
|
126
152
|
end
|
127
153
|
end
|
@@ -23,7 +23,8 @@ module SecureHeaders
|
|
23
23
|
# directive values: these values will directly translate into source directives
|
24
24
|
default_src: %w(https: 'self'),
|
25
25
|
frame_src: %w('self' *.twimg.com itunes.apple.com),
|
26
|
-
|
26
|
+
child_src: %w('self' *.twimg.com itunes.apple.com),
|
27
|
+
connect_src: %w(wss:),
|
27
28
|
font_src: %w('self' data:),
|
28
29
|
img_src: %w(mycdn.com data:),
|
29
30
|
media_src: %w(utoob.com),
|
@@ -31,7 +32,6 @@ module SecureHeaders
|
|
31
32
|
script_src: %w('self'),
|
32
33
|
style_src: %w('unsafe-inline'),
|
33
34
|
base_uri: %w('self'),
|
34
|
-
child_src: %w('self'),
|
35
35
|
form_action: %w('self' github.com),
|
36
36
|
frame_ancestors: %w('none'),
|
37
37
|
plugin_types: %w(application/x-shockwave-flash),
|
@@ -90,8 +90,7 @@ module SecureHeaders
|
|
90
90
|
config = Configuration.default do |config|
|
91
91
|
config.csp = {
|
92
92
|
default_src: %w('self'),
|
93
|
-
child_src: %w('self')
|
94
|
-
frame_src: %w('self')
|
93
|
+
child_src: %w('self')
|
95
94
|
}
|
96
95
|
end
|
97
96
|
firefox_request = Rack::Request.new(request.env.merge("HTTP_USER_AGENT" => USER_AGENTS[:firefox]))
|
@@ -102,6 +101,8 @@ module SecureHeaders
|
|
102
101
|
SecureHeaders.override_content_security_policy_directives(firefox_request, script_src: %w('self'))
|
103
102
|
|
104
103
|
hash = SecureHeaders.header_hash_for(firefox_request)
|
104
|
+
|
105
|
+
# child-src is translated to frame-src
|
105
106
|
expect(hash[CSP::HEADER_NAME]).to eq("default-src 'self'; frame-src 'self'; script-src 'self'")
|
106
107
|
end
|
107
108
|
|
data/spec/spec_helper.rb
CHANGED
@@ -12,7 +12,8 @@ require File.join(File.dirname(__FILE__), '..', 'lib', 'secure_headers')
|
|
12
12
|
|
13
13
|
USER_AGENTS = {
|
14
14
|
edge: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.246",
|
15
|
-
firefox:
|
15
|
+
firefox: "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:14.0) Gecko/20100101 Firefox/14.0.1",
|
16
|
+
firefox46: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:46.0) Gecko/20100101 Firefox/46.0",
|
16
17
|
chrome: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.56 Safari/536.5',
|
17
18
|
ie: 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/5.0)',
|
18
19
|
opera: 'Opera/9.80 (Windows NT 6.1; U; es-ES) Presto/2.9.181 Version/12.00',
|
data/upgrading-to-3-0.md
CHANGED
@@ -8,7 +8,7 @@ Changes
|
|
8
8
|
| Global configuration | `SecureHeaders::Configuration.configure` block | `SecureHeaders::Configuration.default` block |
|
9
9
|
| All headers besides HPKP and CSP | Accept hashes as config values | Must be strings (validated during configuration) |
|
10
10
|
| CSP directive values | Accepted space delimited strings OR arrays of strings | Must be arrays of strings |
|
11
|
-
| CSP Nonce values in views | `@content_security_policy_nonce` | `
|
11
|
+
| CSP Nonce values in views | `@content_security_policy_nonce` | `content_security_policy_nonce(:script)` or `content_security_policy_nonce(:style)` |
|
12
12
|
| nonce is no longer a source expression | `config.csp = "'self' 'nonce'"` | Remove `'nonce'` from source expression and use [nonce helpers](https://github.com/twitter/secureheaders#nonce). |
|
13
13
|
| `self`/`none` source expressions | Could be `self` / `none` / `'self'` / `'none'` | Must be `'self'` or `'none'` |
|
14
14
|
| `inline` / `eval` source expressions | Could be `inline`, `eval`, `'unsafe-inline'`, or `'unsafe-eval'` | Must be `'unsafe-eval'` or `'unsafe-inline'` |
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: secure_headers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Neil Matatall
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-07-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -45,6 +45,8 @@ executables: []
|
|
45
45
|
extensions: []
|
46
46
|
extra_rdoc_files: []
|
47
47
|
files:
|
48
|
+
- ".github/ISSUE_TEMPLATE.md"
|
49
|
+
- ".github/PULL_REQUEST_TEMPLATE.md"
|
48
50
|
- ".gitignore"
|
49
51
|
- ".rspec"
|
50
52
|
- ".ruby-gemset"
|