secure_headers 6.3.4 → 7.3.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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -2
  3. data/Gemfile +2 -0
  4. data/README.md +81 -15
  5. data/lib/secure_headers/configuration.rb +64 -13
  6. data/lib/secure_headers/headers/clear_site_data.rb +31 -33
  7. data/lib/secure_headers/headers/content_security_policy.rb +80 -46
  8. data/lib/secure_headers/headers/content_security_policy_config.rb +17 -58
  9. data/lib/secure_headers/headers/cookie.rb +4 -6
  10. data/lib/secure_headers/headers/expect_certificate_transparency.rb +20 -22
  11. data/lib/secure_headers/headers/policy_management.rb +66 -18
  12. data/lib/secure_headers/headers/referrer_policy.rb +20 -22
  13. data/lib/secure_headers/headers/reporting_endpoints.rb +54 -0
  14. data/lib/secure_headers/headers/strict_transport_security.rb +13 -15
  15. data/lib/secure_headers/headers/x_content_type_options.rb +14 -16
  16. data/lib/secure_headers/headers/x_download_options.rb +14 -16
  17. data/lib/secure_headers/headers/x_frame_options.rb +14 -16
  18. data/lib/secure_headers/headers/x_permitted_cross_domain_policies.rb +14 -16
  19. data/lib/secure_headers/headers/x_xss_protection.rb +14 -16
  20. data/lib/secure_headers/middleware.rb +11 -7
  21. data/lib/secure_headers/railtie.rb +11 -8
  22. data/lib/secure_headers/task_helper.rb +65 -0
  23. data/lib/secure_headers/version.rb +1 -1
  24. data/lib/secure_headers/view_helper.rb +7 -6
  25. data/lib/secure_headers.rb +26 -2
  26. data/lib/tasks/tasks.rake +4 -53
  27. data/secure_headers.gemspec +19 -7
  28. metadata +38 -70
  29. data/.github/ISSUE_TEMPLATE.md +0 -41
  30. data/.github/PULL_REQUEST_TEMPLATE.md +0 -20
  31. data/.github/workflows/build.yml +0 -24
  32. data/.github/workflows/github-release.yml +0 -28
  33. data/.gitignore +0 -13
  34. data/.rspec +0 -3
  35. data/.rubocop.yml +0 -4
  36. data/.ruby-gemset +0 -1
  37. data/.ruby-version +0 -1
  38. data/CODE_OF_CONDUCT.md +0 -46
  39. data/CONTRIBUTING.md +0 -41
  40. data/Guardfile +0 -13
  41. data/Rakefile +0 -32
  42. data/docs/cookies.md +0 -65
  43. data/docs/hashes.md +0 -64
  44. data/docs/named_overrides_and_appends.md +0 -104
  45. data/docs/per_action_configuration.md +0 -139
  46. data/docs/sinatra.md +0 -25
  47. data/docs/upgrading-to-3-0.md +0 -42
  48. data/docs/upgrading-to-4-0.md +0 -35
  49. data/docs/upgrading-to-5-0.md +0 -15
  50. data/docs/upgrading-to-6-0.md +0 -50
  51. data/spec/lib/secure_headers/configuration_spec.rb +0 -121
  52. data/spec/lib/secure_headers/headers/clear_site_data_spec.rb +0 -87
  53. data/spec/lib/secure_headers/headers/content_security_policy_spec.rb +0 -190
  54. data/spec/lib/secure_headers/headers/cookie_spec.rb +0 -179
  55. data/spec/lib/secure_headers/headers/expect_certificate_transparency_spec.rb +0 -42
  56. data/spec/lib/secure_headers/headers/policy_management_spec.rb +0 -264
  57. data/spec/lib/secure_headers/headers/referrer_policy_spec.rb +0 -91
  58. data/spec/lib/secure_headers/headers/strict_transport_security_spec.rb +0 -33
  59. data/spec/lib/secure_headers/headers/x_content_type_options_spec.rb +0 -31
  60. data/spec/lib/secure_headers/headers/x_download_options_spec.rb +0 -29
  61. data/spec/lib/secure_headers/headers/x_frame_options_spec.rb +0 -36
  62. data/spec/lib/secure_headers/headers/x_permitted_cross_domain_policies_spec.rb +0 -48
  63. data/spec/lib/secure_headers/headers/x_xss_protection_spec.rb +0 -47
  64. data/spec/lib/secure_headers/middleware_spec.rb +0 -117
  65. data/spec/lib/secure_headers/view_helpers_spec.rb +0 -191
  66. data/spec/lib/secure_headers_spec.rb +0 -516
  67. data/spec/spec_helper.rb +0 -64
@@ -1,179 +0,0 @@
1
- # frozen_string_literal: true
2
- require "spec_helper"
3
-
4
- module SecureHeaders
5
- describe Cookie do
6
- let(:raw_cookie) { "_session=thisisatest" }
7
-
8
- it "does not tamper with cookies when using OPT_OUT is used" do
9
- cookie = Cookie.new(raw_cookie, OPT_OUT)
10
- expect(cookie.to_s).to eq(raw_cookie)
11
- end
12
-
13
- it "applies httponly, secure, and samesite by default" do
14
- cookie = Cookie.new(raw_cookie, nil)
15
- expect(cookie.to_s).to eq("_session=thisisatest; secure; HttpOnly; SameSite=Lax")
16
- end
17
-
18
- it "preserves existing attributes" do
19
- cookie = Cookie.new("_session=thisisatest; secure", secure: true, httponly: OPT_OUT, samesite: OPT_OUT)
20
- expect(cookie.to_s).to eq("_session=thisisatest; secure")
21
- end
22
-
23
- it "prevents duplicate flagging of attributes" do
24
- cookie = Cookie.new("_session=thisisatest; secure", secure: true, httponly: OPT_OUT)
25
- expect(cookie.to_s.scan(/secure/i).count).to eq(1)
26
- end
27
-
28
- context "Secure cookies" do
29
- context "when configured with a boolean" do
30
- it "flags cookies as Secure" do
31
- cookie = Cookie.new(raw_cookie, secure: true, httponly: OPT_OUT, samesite: OPT_OUT)
32
- expect(cookie.to_s).to eq("_session=thisisatest; secure")
33
- end
34
- end
35
-
36
- context "when configured with a Hash" do
37
- it "flags cookies as Secure when whitelisted" do
38
- cookie = Cookie.new(raw_cookie, secure: { only: ["_session"]}, httponly: OPT_OUT, samesite: OPT_OUT)
39
- expect(cookie.to_s).to eq("_session=thisisatest; secure")
40
- end
41
-
42
- it "does not flag cookies as Secure when excluded" do
43
- cookie = Cookie.new(raw_cookie, secure: { except: ["_session"] }, httponly: OPT_OUT, samesite: OPT_OUT)
44
- expect(cookie.to_s).to eq("_session=thisisatest")
45
- end
46
- end
47
- end
48
-
49
- context "HttpOnly cookies" do
50
- context "when configured with a boolean" do
51
- it "flags cookies as HttpOnly" do
52
- cookie = Cookie.new(raw_cookie, httponly: true, secure: OPT_OUT, samesite: OPT_OUT)
53
- expect(cookie.to_s).to eq("_session=thisisatest; HttpOnly")
54
- end
55
- end
56
-
57
- context "when configured with a Hash" do
58
- it "flags cookies as HttpOnly when whitelisted" do
59
- cookie = Cookie.new(raw_cookie, httponly: { only: ["_session"]}, secure: OPT_OUT, samesite: OPT_OUT)
60
- expect(cookie.to_s).to eq("_session=thisisatest; HttpOnly")
61
- end
62
-
63
- it "does not flag cookies as HttpOnly when excluded" do
64
- cookie = Cookie.new(raw_cookie, httponly: { except: ["_session"] }, secure: OPT_OUT, samesite: OPT_OUT)
65
- expect(cookie.to_s).to eq("_session=thisisatest")
66
- end
67
- end
68
- end
69
-
70
- context "SameSite cookies" do
71
- %w(None Lax Strict).each do |flag|
72
- it "flags SameSite=#{flag}" do
73
- cookie = Cookie.new(raw_cookie, samesite: { flag.downcase.to_sym => { only: ["_session"] } }, secure: OPT_OUT, httponly: OPT_OUT)
74
- expect(cookie.to_s).to eq("_session=thisisatest; SameSite=#{flag}")
75
- end
76
-
77
- it "flags SameSite=#{flag} when configured with a boolean" do
78
- cookie = Cookie.new(raw_cookie, samesite: { flag.downcase.to_sym => true}, secure: OPT_OUT, httponly: OPT_OUT)
79
- expect(cookie.to_s).to eq("_session=thisisatest; SameSite=#{flag}")
80
- end
81
-
82
- it "does not flag cookies as SameSite=#{flag} when excluded" do
83
- cookie = Cookie.new(raw_cookie, samesite: { flag.downcase.to_sym => { except: ["_session"] } }, secure: OPT_OUT, httponly: OPT_OUT)
84
- expect(cookie.to_s).to eq("_session=thisisatest")
85
- end
86
- end
87
-
88
- it "flags SameSite=Strict when configured with a boolean" do
89
- cookie = Cookie.new(raw_cookie, {samesite: { strict: true}, secure: OPT_OUT, httponly: OPT_OUT})
90
- expect(cookie.to_s).to eq("_session=thisisatest; SameSite=Strict")
91
- end
92
-
93
- it "flags properly when both lax and strict are configured" do
94
- raw_cookie = "_session=thisisatest"
95
- cookie = Cookie.new(raw_cookie, samesite: { strict: { only: ["_session"] }, lax: { only: ["_additional_session"] } }, secure: OPT_OUT, httponly: OPT_OUT)
96
- expect(cookie.to_s).to eq("_session=thisisatest; SameSite=Strict")
97
- end
98
-
99
- it "ignores configuration if the cookie is already flagged" do
100
- raw_cookie = "_session=thisisatest; SameSite=Strict"
101
- cookie = Cookie.new(raw_cookie, samesite: { lax: true }, secure: OPT_OUT, httponly: OPT_OUT)
102
- expect(cookie.to_s).to eq(raw_cookie)
103
- end
104
-
105
- it "samesite: true sets all cookies to samesite=lax" do
106
- raw_cookie = "_session=thisisatest"
107
- cookie = Cookie.new(raw_cookie, samesite: true, secure: OPT_OUT, httponly: OPT_OUT)
108
- expect(cookie.to_s).to eq("_session=thisisatest; SameSite=Lax")
109
- end
110
- end
111
- end
112
-
113
- context "with an invalid configuration" do
114
- it "raises an exception when not configured with a Hash" do
115
- expect do
116
- Cookie.validate_config!("configuration")
117
- end.to raise_error(CookiesConfigError)
118
- end
119
-
120
- it "raises an exception when configured without a boolean(true or OPT_OUT)/Hash" do
121
- expect do
122
- Cookie.validate_config!(secure: "true")
123
- end.to raise_error(CookiesConfigError)
124
- end
125
-
126
- it "raises an exception when configured with false" do
127
- expect do
128
- Cookie.validate_config!(secure: false)
129
- end.to raise_error(CookiesConfigError)
130
- end
131
-
132
- it "raises an exception when both only and except filters are provided" do
133
- expect do
134
- Cookie.validate_config!(secure: { only: [], except: [] })
135
- end.to raise_error(CookiesConfigError)
136
- end
137
-
138
- it "raises an exception when SameSite is not configured with a Hash" do
139
- expect do
140
- Cookie.validate_config!(samesite: true)
141
- end.to raise_error(CookiesConfigError)
142
- end
143
-
144
- cookie_options = %i(none lax strict)
145
- cookie_options.each do |flag|
146
- (cookie_options - [flag]).each do |other_flag|
147
- it "raises an exception when SameSite #{flag} and #{other_flag} enforcement modes are configured with booleans" do
148
- expect do
149
- Cookie.validate_config!(samesite: { flag => true, other_flag => true})
150
- end.to raise_error(CookiesConfigError)
151
- end
152
- end
153
- end
154
-
155
- it "raises an exception when SameSite lax and strict enforcement modes are configured with booleans" do
156
- expect do
157
- Cookie.validate_config!(samesite: { lax: true, strict: { only: ["_anything"] } })
158
- end.to raise_error(CookiesConfigError)
159
- end
160
-
161
- it "raises an exception when both only and except filters are provided to SameSite configurations" do
162
- expect do
163
- Cookie.validate_config!(samesite: { lax: { only: ["_anything"], except: ["_anythingelse"] } })
164
- end.to raise_error(CookiesConfigError)
165
- end
166
-
167
- it "raises an exception when both lax and strict only filters are provided to SameSite configurations" do
168
- expect do
169
- Cookie.validate_config!(samesite: { lax: { only: ["_anything"] }, strict: { only: ["_anything"] } })
170
- end.to raise_error(CookiesConfigError)
171
- end
172
-
173
- it "raises an exception when both lax and strict only filters are provided to SameSite configurations" do
174
- expect do
175
- Cookie.validate_config!(samesite: { lax: { except: ["_anything"] }, strict: { except: ["_anything"] } })
176
- end.to raise_error(CookiesConfigError)
177
- end
178
- end
179
- end
@@ -1,42 +0,0 @@
1
- # frozen_string_literal: true
2
- require "spec_helper"
3
-
4
- module SecureHeaders
5
- describe ExpectCertificateTransparency do
6
- specify { expect(ExpectCertificateTransparency.new(max_age: 1234, enforce: true).value).to eq("enforce, max-age=1234") }
7
- specify { expect(ExpectCertificateTransparency.new(max_age: 1234, enforce: false).value).to eq("max-age=1234") }
8
- specify { expect(ExpectCertificateTransparency.new(max_age: 1234, enforce: "yolocopter").value).to eq("max-age=1234") }
9
- specify { expect(ExpectCertificateTransparency.new(max_age: 1234, report_uri: "https://report-uri.io/expect-ct").value).to eq("max-age=1234, report-uri=\"https://report-uri.io/expect-ct\"") }
10
- specify do
11
- config = { enforce: true, max_age: 1234, report_uri: "https://report-uri.io/expect-ct" }
12
- header_value = "enforce, max-age=1234, report-uri=\"https://report-uri.io/expect-ct\""
13
- expect(ExpectCertificateTransparency.new(config).value).to eq(header_value)
14
- end
15
-
16
- context "with an invalid configuration" do
17
- it "raises an exception when configuration isn't a hash" do
18
- expect do
19
- ExpectCertificateTransparency.validate_config!(%w(a))
20
- end.to raise_error(ExpectCertificateTransparencyConfigError)
21
- end
22
-
23
- it "raises an exception when max-age is not provided" do
24
- expect do
25
- ExpectCertificateTransparency.validate_config!(foo: "bar")
26
- end.to raise_error(ExpectCertificateTransparencyConfigError)
27
- end
28
-
29
- it "raises an exception with an invalid max-age" do
30
- expect do
31
- ExpectCertificateTransparency.validate_config!(max_age: "abc123")
32
- end.to raise_error(ExpectCertificateTransparencyConfigError)
33
- end
34
-
35
- it "raises an exception with an invalid enforce value" do
36
- expect do
37
- ExpectCertificateTransparency.validate_config!(enforce: "brokenstring")
38
- end.to raise_error(ExpectCertificateTransparencyConfigError)
39
- end
40
- end
41
- end
42
- end
@@ -1,264 +0,0 @@
1
- # frozen_string_literal: true
2
- require "spec_helper"
3
-
4
- module SecureHeaders
5
- describe PolicyManagement do
6
- before(:each) do
7
- reset_config
8
- Configuration.default
9
- end
10
-
11
- let (:default_opts) do
12
- {
13
- default_src: %w(https:),
14
- img_src: %w(https: data:),
15
- script_src: %w('unsafe-inline' 'unsafe-eval' https: data:),
16
- style_src: %w('unsafe-inline' https: about:),
17
- report_uri: %w(/csp_report)
18
- }
19
- end
20
-
21
- describe "#validate_config!" do
22
- it "accepts all keys" do
23
- # (pulled from README)
24
- config = {
25
- # "meta" values. these will shape the header, but the values are not included in the header.
26
- report_only: false,
27
- preserve_schemes: true, # default: false. Schemes are removed from host sources to save bytes and discourage mixed content.
28
-
29
- # directive values: these values will directly translate into source directives
30
- default_src: %w(https: 'self'),
31
-
32
- base_uri: %w('self'),
33
- block_all_mixed_content: true, # see [http://www.w3.org/TR/mixed-content/](http://www.w3.org/TR/mixed-content/)
34
- connect_src: %w(wss:),
35
- child_src: %w('self' *.twimg.com itunes.apple.com),
36
- font_src: %w('self' data:),
37
- form_action: %w('self' github.com),
38
- frame_ancestors: %w('none'),
39
- frame_src: %w('self' *.twimg.com itunes.apple.com),
40
- img_src: %w(mycdn.com data:),
41
- manifest_src: %w(manifest.com),
42
- media_src: %w(utoob.com),
43
- navigate_to: %w(netscape.com),
44
- object_src: %w('self'),
45
- plugin_types: %w(application/x-shockwave-flash),
46
- prefetch_src: %w(fetch.com),
47
- require_sri_for: %w(script style),
48
- script_src: %w('self'),
49
- style_src: %w('unsafe-inline'),
50
- upgrade_insecure_requests: true, # see https://www.w3.org/TR/upgrade-insecure-requests/
51
- worker_src: %w(worker.com),
52
- script_src_elem: %w(example.com),
53
- script_src_attr: %w(example.com),
54
- style_src_elem: %w(example.com),
55
- style_src_attr: %w(example.com),
56
-
57
- report_uri: %w(https://example.com/uri-directive),
58
- }
59
-
60
- ContentSecurityPolicy.validate_config!(ContentSecurityPolicyConfig.new(config))
61
- end
62
-
63
- it "requires a :default_src value" do
64
- expect do
65
- ContentSecurityPolicy.validate_config!(ContentSecurityPolicyConfig.new(script_src: %w('self')))
66
- end.to raise_error(ContentSecurityPolicyConfigError)
67
- end
68
-
69
- it "requires a :script_src value" do
70
- expect do
71
- ContentSecurityPolicy.validate_config!(ContentSecurityPolicyConfig.new(default_src: %w('self')))
72
- end.to raise_error(ContentSecurityPolicyConfigError)
73
- end
74
-
75
- it "accepts OPT_OUT as a script-src value" do
76
- expect do
77
- ContentSecurityPolicy.validate_config!(ContentSecurityPolicyConfig.new(default_src: %w('self'), script_src: OPT_OUT))
78
- end.to_not raise_error
79
- end
80
-
81
- it "requires :report_only to be a truthy value" do
82
- expect do
83
- ContentSecurityPolicy.validate_config!(ContentSecurityPolicyConfig.new(default_opts.merge(report_only: "steve")))
84
- end.to raise_error(ContentSecurityPolicyConfigError)
85
- end
86
-
87
- it "requires :preserve_schemes to be a truthy value" do
88
- expect do
89
- ContentSecurityPolicy.validate_config!(ContentSecurityPolicyConfig.new(default_opts.merge(preserve_schemes: "steve")))
90
- end.to raise_error(ContentSecurityPolicyConfigError)
91
- end
92
-
93
- it "requires :block_all_mixed_content to be a boolean value" do
94
- expect do
95
- ContentSecurityPolicy.validate_config!(ContentSecurityPolicyConfig.new(default_opts.merge(block_all_mixed_content: "steve")))
96
- end.to raise_error(ContentSecurityPolicyConfigError)
97
- end
98
-
99
- it "requires :upgrade_insecure_requests to be a boolean value" do
100
- expect do
101
- ContentSecurityPolicy.validate_config!(ContentSecurityPolicyConfig.new(default_opts.merge(upgrade_insecure_requests: "steve")))
102
- end.to raise_error(ContentSecurityPolicyConfigError)
103
- end
104
-
105
- it "requires all source lists to be an array of strings" do
106
- expect do
107
- ContentSecurityPolicy.validate_config!(ContentSecurityPolicyConfig.new(default_src: "steve"))
108
- end.to raise_error(ContentSecurityPolicyConfigError)
109
- end
110
-
111
- it "allows nil values" do
112
- expect do
113
- ContentSecurityPolicy.validate_config!(ContentSecurityPolicyConfig.new(default_src: %w('self'), script_src: ["https:", nil]))
114
- end.to_not raise_error
115
- end
116
-
117
- it "rejects unknown directives / config" do
118
- expect do
119
- ContentSecurityPolicy.validate_config!(ContentSecurityPolicyConfig.new(default_src: %w('self'), default_src_totally_mispelled: "steve"))
120
- end.to raise_error(ContentSecurityPolicyConfigError)
121
- end
122
-
123
- # this is mostly to ensure people don't use the antiquated shorthands common in other configs
124
- it "performs light validation on source lists" do
125
- expect do
126
- ContentSecurityPolicy.validate_config!(ContentSecurityPolicyConfig.new(default_src: %w(self none inline eval), script_src: %w('self')))
127
- end.to raise_error(ContentSecurityPolicyConfigError)
128
- end
129
-
130
- it "rejects anything not of the form allow-* as a sandbox value" do
131
- expect do
132
- ContentSecurityPolicy.validate_config!(ContentSecurityPolicyConfig.new(default_opts.merge(sandbox: ["steve"])))
133
- end.to raise_error(ContentSecurityPolicyConfigError)
134
- end
135
-
136
- it "accepts anything of the form allow-* as a sandbox value " do
137
- expect do
138
- ContentSecurityPolicy.validate_config!(ContentSecurityPolicyConfig.new(default_opts.merge(sandbox: ["allow-foo"])))
139
- end.to_not raise_error
140
- end
141
-
142
- it "accepts true as a sandbox policy" do
143
- expect do
144
- ContentSecurityPolicy.validate_config!(ContentSecurityPolicyConfig.new(default_opts.merge(sandbox: true)))
145
- end.to_not raise_error
146
- end
147
-
148
- it "rejects anything not of the form type/subtype as a plugin-type value" do
149
- expect do
150
- ContentSecurityPolicy.validate_config!(ContentSecurityPolicyConfig.new(default_opts.merge(plugin_types: ["steve"])))
151
- end.to raise_error(ContentSecurityPolicyConfigError)
152
- end
153
-
154
- it "accepts anything of the form type/subtype as a plugin-type value " do
155
- expect do
156
- ContentSecurityPolicy.validate_config!(ContentSecurityPolicyConfig.new(default_opts.merge(plugin_types: ["application/pdf"])))
157
- end.to_not raise_error
158
- end
159
-
160
- it "doesn't allow report_only to be set in a non-report-only config" do
161
- expect do
162
- ContentSecurityPolicy.validate_config!(ContentSecurityPolicyConfig.new(default_opts.merge(report_only: true)))
163
- end.to raise_error(ContentSecurityPolicyConfigError)
164
- end
165
-
166
- it "allows report_only to be set in a report-only config" do
167
- expect do
168
- ContentSecurityPolicy.validate_config!(ContentSecurityPolicyReportOnlyConfig.new(default_opts.merge(report_only: true)))
169
- end.to_not raise_error
170
- end
171
- end
172
-
173
- describe "#combine_policies" do
174
- before(:each) do
175
- reset_config
176
- end
177
- it "combines the default-src value with the override if the directive was unconfigured" do
178
- Configuration.default do |config|
179
- config.csp = {
180
- default_src: %w(https:),
181
- script_src: %w('self'),
182
- }
183
- end
184
- default_policy = Configuration.dup
185
- combined_config = ContentSecurityPolicy.combine_policies(default_policy.csp.to_h, style_src: %w(anothercdn.com))
186
- csp = ContentSecurityPolicy.new(combined_config)
187
- expect(csp.name).to eq(ContentSecurityPolicyConfig::HEADER_NAME)
188
- expect(csp.value).to eq("default-src https:; script-src 'self'; style-src https: anothercdn.com")
189
- end
190
-
191
- it "combines directives where the original value is nil and the hash is frozen" do
192
- Configuration.default do |config|
193
- config.csp = {
194
- default_src: %w('self'),
195
- script_src: %w('self'),
196
- report_only: false
197
- }.freeze
198
- end
199
- report_uri = "https://report-uri.io/asdf"
200
- default_policy = Configuration.dup
201
- combined_config = ContentSecurityPolicy.combine_policies(default_policy.csp.to_h, report_uri: [report_uri])
202
- csp = ContentSecurityPolicy.new(combined_config)
203
- expect(csp.value).to include("report-uri #{report_uri}")
204
- end
205
-
206
- it "does not combine the default-src value for directives that don't fall back to default sources" do
207
- Configuration.default do |config|
208
- config.csp = {
209
- default_src: %w('self'),
210
- script_src: %w('self'),
211
- report_only: false
212
- }.freeze
213
- end
214
- non_default_source_additions = ContentSecurityPolicy::NON_FETCH_SOURCES.each_with_object({}) do |directive, hash|
215
- hash[directive] = %w("http://example.org)
216
- end
217
- default_policy = Configuration.dup
218
- combined_config = ContentSecurityPolicy.combine_policies(default_policy.csp.to_h, non_default_source_additions)
219
-
220
- ContentSecurityPolicy::NON_FETCH_SOURCES.each do |directive|
221
- expect(combined_config[directive]).to eq(%w("http://example.org))
222
- end
223
- end
224
-
225
- it "overrides the report_only flag" do
226
- Configuration.default do |config|
227
- config.csp = {
228
- default_src: %w('self'),
229
- script_src: %w('self'),
230
- report_only: false
231
- }
232
- end
233
- default_policy = Configuration.dup
234
- combined_config = ContentSecurityPolicy.combine_policies(default_policy.csp.to_h, report_only: true)
235
- csp = ContentSecurityPolicy.new(combined_config)
236
- expect(csp.name).to eq(ContentSecurityPolicyReportOnlyConfig::HEADER_NAME)
237
- end
238
-
239
- it "overrides the :block_all_mixed_content flag" do
240
- Configuration.default do |config|
241
- config.csp = {
242
- default_src: %w(https:),
243
- script_src: %w('self'),
244
- block_all_mixed_content: false
245
- }
246
- end
247
- default_policy = Configuration.dup
248
- combined_config = ContentSecurityPolicy.combine_policies(default_policy.csp.to_h, block_all_mixed_content: true)
249
- csp = ContentSecurityPolicy.new(combined_config)
250
- expect(csp.value).to eq("default-src https:; block-all-mixed-content; script-src 'self'")
251
- end
252
-
253
- it "raises an error if appending to a OPT_OUT policy" do
254
- Configuration.default do |config|
255
- config.csp = OPT_OUT
256
- end
257
- default_policy = Configuration.dup
258
- expect do
259
- ContentSecurityPolicy.combine_policies(default_policy.csp.to_h, script_src: %w(anothercdn.com))
260
- end.to raise_error(ContentSecurityPolicyConfigError)
261
- end
262
- end
263
- end
264
- end
@@ -1,91 +0,0 @@
1
- # frozen_string_literal: true
2
- require "spec_helper"
3
-
4
- module SecureHeaders
5
- describe ReferrerPolicy do
6
- specify { expect(ReferrerPolicy.make_header).to eq([ReferrerPolicy::HEADER_NAME, "origin-when-cross-origin"]) }
7
- specify { expect(ReferrerPolicy.make_header("no-referrer")).to eq([ReferrerPolicy::HEADER_NAME, "no-referrer"]) }
8
- specify { expect(ReferrerPolicy.make_header(%w(origin-when-cross-origin strict-origin-when-cross-origin))).to eq([ReferrerPolicy::HEADER_NAME, "origin-when-cross-origin, strict-origin-when-cross-origin"]) }
9
-
10
- context "valid configuration values" do
11
- it "accepts 'no-referrer'" do
12
- expect do
13
- ReferrerPolicy.validate_config!("no-referrer")
14
- end.not_to raise_error
15
- end
16
-
17
- it "accepts 'no-referrer-when-downgrade'" do
18
- expect do
19
- ReferrerPolicy.validate_config!("no-referrer-when-downgrade")
20
- end.not_to raise_error
21
- end
22
-
23
- it "accepts 'same-origin'" do
24
- expect do
25
- ReferrerPolicy.validate_config!("same-origin")
26
- end.not_to raise_error
27
- end
28
-
29
- it "accepts 'strict-origin'" do
30
- expect do
31
- ReferrerPolicy.validate_config!("strict-origin")
32
- end.not_to raise_error
33
- end
34
-
35
- it "accepts 'strict-origin-when-cross-origin'" do
36
- expect do
37
- ReferrerPolicy.validate_config!("strict-origin-when-cross-origin")
38
- end.not_to raise_error
39
- end
40
-
41
- it "accepts 'origin'" do
42
- expect do
43
- ReferrerPolicy.validate_config!("origin")
44
- end.not_to raise_error
45
- end
46
-
47
- it "accepts 'origin-when-cross-origin'" do
48
- expect do
49
- ReferrerPolicy.validate_config!("origin-when-cross-origin")
50
- end.not_to raise_error
51
- end
52
-
53
- it "accepts 'unsafe-url'" do
54
- expect do
55
- ReferrerPolicy.validate_config!("unsafe-url")
56
- end.not_to raise_error
57
- end
58
-
59
- it "accepts nil" do
60
- expect do
61
- ReferrerPolicy.validate_config!(nil)
62
- end.not_to raise_error
63
- end
64
-
65
- it "accepts array of policy values" do
66
- expect do
67
- ReferrerPolicy.validate_config!(
68
- %w(
69
- origin-when-cross-origin
70
- strict-origin-when-cross-origin
71
- )
72
- )
73
- end.not_to raise_error
74
- end
75
- end
76
-
77
- context "invalid configuration values" do
78
- it "doesn't accept invalid values" do
79
- expect do
80
- ReferrerPolicy.validate_config!("open")
81
- end.to raise_error(ReferrerPolicyConfigError)
82
- end
83
-
84
- it "doesn't accept invalid types" do
85
- expect do
86
- ReferrerPolicy.validate_config!({})
87
- end.to raise_error(TypeError)
88
- end
89
- end
90
- end
91
- end
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
- require "spec_helper"
3
-
4
- module SecureHeaders
5
- describe StrictTransportSecurity do
6
- describe "#value" do
7
- specify { expect(StrictTransportSecurity.make_header).to eq([StrictTransportSecurity::HEADER_NAME, StrictTransportSecurity::DEFAULT_VALUE]) }
8
- specify { expect(StrictTransportSecurity.make_header("max-age=1234; includeSubdomains; preload")).to eq([StrictTransportSecurity::HEADER_NAME, "max-age=1234; includeSubdomains; preload"]) }
9
-
10
- context "with an invalid configuration" do
11
- context "with a string argument" do
12
- it "raises an exception with an invalid max-age" do
13
- expect do
14
- StrictTransportSecurity.validate_config!("max-age=abc123")
15
- end.to raise_error(STSConfigError)
16
- end
17
-
18
- it "raises an exception if max-age is not supplied" do
19
- expect do
20
- StrictTransportSecurity.validate_config!("includeSubdomains")
21
- end.to raise_error(STSConfigError)
22
- end
23
-
24
- it "raises an exception with an invalid format" do
25
- expect do
26
- StrictTransportSecurity.validate_config!("max-age=123includeSubdomains")
27
- end.to raise_error(STSConfigError)
28
- end
29
- end
30
- end
31
- end
32
- end
33
- end
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
- require "spec_helper"
3
-
4
- module SecureHeaders
5
- describe XContentTypeOptions do
6
- describe "#value" do
7
- specify { expect(XContentTypeOptions.make_header).to eq([XContentTypeOptions::HEADER_NAME, XContentTypeOptions::DEFAULT_VALUE]) }
8
- specify { expect(XContentTypeOptions.make_header("nosniff")).to eq([XContentTypeOptions::HEADER_NAME, "nosniff"]) }
9
-
10
- context "invalid configuration values" do
11
- it "accepts nosniff" do
12
- expect do
13
- XContentTypeOptions.validate_config!("nosniff")
14
- end.not_to raise_error
15
- end
16
-
17
- it "accepts nil" do
18
- expect do
19
- XContentTypeOptions.validate_config!(nil)
20
- end.not_to raise_error
21
- end
22
-
23
- it "doesn't accept anything besides no-sniff" do
24
- expect do
25
- XContentTypeOptions.validate_config!("donkey")
26
- end.to raise_error(XContentTypeOptionsConfigError)
27
- end
28
- end
29
- end
30
- end
31
- end
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
- require "spec_helper"
3
-
4
- module SecureHeaders
5
- describe XDownloadOptions do
6
- specify { expect(XDownloadOptions.make_header).to eq([XDownloadOptions::HEADER_NAME, XDownloadOptions::DEFAULT_VALUE]) }
7
- specify { expect(XDownloadOptions.make_header("noopen")).to eq([XDownloadOptions::HEADER_NAME, "noopen"]) }
8
-
9
- context "invalid configuration values" do
10
- it "accepts noopen" do
11
- expect do
12
- XDownloadOptions.validate_config!("noopen")
13
- end.not_to raise_error
14
- end
15
-
16
- it "accepts nil" do
17
- expect do
18
- XDownloadOptions.validate_config!(nil)
19
- end.not_to raise_error
20
- end
21
-
22
- it "doesn't accept anything besides noopen" do
23
- expect do
24
- XDownloadOptions.validate_config!("open")
25
- end.to raise_error(XDOConfigError)
26
- end
27
- end
28
- end
29
- end