secure_headers 7.0.0 → 7.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +13 -13
  3. data/lib/secure_headers/configuration.rb +1 -1
  4. data/lib/secure_headers/headers/clear_site_data.rb +4 -4
  5. data/lib/secure_headers/headers/content_security_policy.rb +2 -2
  6. data/lib/secure_headers/headers/content_security_policy_config.rb +2 -2
  7. data/lib/secure_headers/headers/expect_certificate_transparency.rb +2 -2
  8. data/lib/secure_headers/headers/policy_management.rb +2 -2
  9. data/lib/secure_headers/headers/referrer_policy.rb +1 -1
  10. data/lib/secure_headers/headers/strict_transport_security.rb +1 -1
  11. data/lib/secure_headers/headers/x_content_type_options.rb +1 -1
  12. data/lib/secure_headers/headers/x_download_options.rb +2 -2
  13. data/lib/secure_headers/headers/x_frame_options.rb +1 -1
  14. data/lib/secure_headers/headers/x_permitted_cross_domain_policies.rb +2 -2
  15. data/lib/secure_headers/headers/x_xss_protection.rb +1 -1
  16. data/lib/secure_headers/railtie.rb +5 -5
  17. data/lib/secure_headers/version.rb +1 -1
  18. data/secure_headers.gemspec +13 -3
  19. metadata +14 -63
  20. data/.github/ISSUE_TEMPLATE.md +0 -41
  21. data/.github/PULL_REQUEST_TEMPLATE.md +0 -20
  22. data/.github/dependabot.yml +0 -6
  23. data/.github/workflows/build.yml +0 -25
  24. data/.github/workflows/github-release.yml +0 -28
  25. data/.gitignore +0 -13
  26. data/.rspec +0 -3
  27. data/.rubocop.yml +0 -4
  28. data/.ruby-gemset +0 -1
  29. data/.ruby-version +0 -1
  30. data/CODE_OF_CONDUCT.md +0 -46
  31. data/CONTRIBUTING.md +0 -41
  32. data/Guardfile +0 -13
  33. data/Rakefile +0 -32
  34. data/docs/cookies.md +0 -65
  35. data/docs/hashes.md +0 -64
  36. data/docs/named_overrides_and_appends.md +0 -104
  37. data/docs/per_action_configuration.md +0 -139
  38. data/docs/sinatra.md +0 -25
  39. data/docs/upgrading-to-3-0.md +0 -42
  40. data/docs/upgrading-to-4-0.md +0 -35
  41. data/docs/upgrading-to-5-0.md +0 -15
  42. data/docs/upgrading-to-6-0.md +0 -50
  43. data/docs/upgrading-to-7-0.md +0 -12
  44. data/spec/lib/secure_headers/configuration_spec.rb +0 -121
  45. data/spec/lib/secure_headers/headers/clear_site_data_spec.rb +0 -87
  46. data/spec/lib/secure_headers/headers/content_security_policy_spec.rb +0 -215
  47. data/spec/lib/secure_headers/headers/cookie_spec.rb +0 -179
  48. data/spec/lib/secure_headers/headers/expect_certificate_transparency_spec.rb +0 -42
  49. data/spec/lib/secure_headers/headers/policy_management_spec.rb +0 -265
  50. data/spec/lib/secure_headers/headers/referrer_policy_spec.rb +0 -91
  51. data/spec/lib/secure_headers/headers/strict_transport_security_spec.rb +0 -33
  52. data/spec/lib/secure_headers/headers/x_content_type_options_spec.rb +0 -31
  53. data/spec/lib/secure_headers/headers/x_download_options_spec.rb +0 -29
  54. data/spec/lib/secure_headers/headers/x_frame_options_spec.rb +0 -36
  55. data/spec/lib/secure_headers/headers/x_permitted_cross_domain_policies_spec.rb +0 -48
  56. data/spec/lib/secure_headers/headers/x_xss_protection_spec.rb +0 -47
  57. data/spec/lib/secure_headers/middleware_spec.rb +0 -117
  58. data/spec/lib/secure_headers/view_helpers_spec.rb +0 -192
  59. data/spec/lib/secure_headers_spec.rb +0 -516
  60. data/spec/spec_helper.rb +0 -64
@@ -1,121 +0,0 @@
1
- # frozen_string_literal: true
2
- require "spec_helper"
3
-
4
- module SecureHeaders
5
- describe Configuration do
6
- before(:each) do
7
- reset_config
8
- end
9
-
10
- it "has a default config" do
11
- expect(Configuration.default).to_not be_nil
12
- end
13
-
14
- it "has an 'noop' override" do
15
- Configuration.default
16
- expect(Configuration.overrides(Configuration::NOOP_OVERRIDE)).to_not be_nil
17
- end
18
-
19
- it "dup results in a copy of the default config" do
20
- Configuration.default
21
- original_configuration = Configuration.send(:default_config)
22
- configuration = Configuration.dup
23
- expect(original_configuration).not_to be(configuration)
24
- Configuration::CONFIG_ATTRIBUTES.each do |attr|
25
- expect(original_configuration.send(attr)).to eq(configuration.send(attr))
26
- end
27
- end
28
-
29
- it "stores an override" do
30
- Configuration.override(:test_override) do |config|
31
- config.x_frame_options = "DENY"
32
- end
33
-
34
- expect(Configuration.overrides(:test_override)).to_not be_nil
35
- end
36
-
37
- describe "#override" do
38
- it "raises on configuring an existing override" do
39
- set_override = Proc.new {
40
- Configuration.override(:test_override) do |config|
41
- config.x_frame_options = "DENY"
42
- end
43
- }
44
-
45
- set_override.call
46
-
47
- expect { set_override.call }
48
- .to raise_error(Configuration::AlreadyConfiguredError, "Configuration already exists")
49
- end
50
-
51
- it "raises when a named append with the given name exists" do
52
- Configuration.named_append(:test_override) do |config|
53
- config.x_frame_options = "DENY"
54
- end
55
-
56
- expect do
57
- Configuration.override(:test_override) do |config|
58
- config.x_frame_options = "SAMEORIGIN"
59
- end
60
- end.to raise_error(Configuration::AlreadyConfiguredError, "Configuration already exists")
61
- end
62
- end
63
-
64
- describe "#named_append" do
65
- it "raises on configuring an existing append" do
66
- set_override = Proc.new {
67
- Configuration.named_append(:test_override) do |config|
68
- config.x_frame_options = "DENY"
69
- end
70
- }
71
-
72
- set_override.call
73
-
74
- expect { set_override.call }
75
- .to raise_error(Configuration::AlreadyConfiguredError, "Configuration already exists")
76
- end
77
-
78
- it "raises when an override with the given name exists" do
79
- Configuration.override(:test_override) do |config|
80
- config.x_frame_options = "DENY"
81
- end
82
-
83
- expect do
84
- Configuration.named_append(:test_override) do |config|
85
- config.x_frame_options = "SAMEORIGIN"
86
- end
87
- end.to raise_error(Configuration::AlreadyConfiguredError, "Configuration already exists")
88
- end
89
- end
90
-
91
- it "deprecates the secure_cookies configuration" do
92
- expect {
93
- Configuration.default do |config|
94
- config.secure_cookies = true
95
- end
96
- }.to raise_error(ArgumentError)
97
- end
98
-
99
- it "gives cookies a default config" do
100
- expect(Configuration.default.cookies).to eq({httponly: true, secure: true, samesite: {lax: true}})
101
- end
102
-
103
- it "allows OPT_OUT" do
104
- Configuration.default do |config|
105
- config.cookies = OPT_OUT
106
- end
107
-
108
- config = Configuration.dup
109
- expect(config.cookies).to eq(OPT_OUT)
110
- end
111
-
112
- it "allows me to be explicit too" do
113
- Configuration.default do |config|
114
- config.cookies = {httponly: true, secure: true, samesite: {lax: false}}
115
- end
116
-
117
- config = Configuration.dup
118
- expect(config.cookies).to eq({httponly: true, secure: true, samesite: {lax: false}})
119
- end
120
- end
121
- end
@@ -1,87 +0,0 @@
1
- # frozen_string_literal: true
2
- require "spec_helper"
3
-
4
- module SecureHeaders
5
- describe ClearSiteData do
6
- describe "make_header" do
7
- it "returns nil with nil config" do
8
- expect(described_class.make_header).to be_nil
9
- end
10
-
11
- it "returns nil with empty config" do
12
- expect(described_class.make_header([])).to be_nil
13
- end
14
-
15
- it "returns nil with opt-out config" do
16
- expect(described_class.make_header(OPT_OUT)).to be_nil
17
- end
18
-
19
- it "returns all types with `true` config" do
20
- name, value = described_class.make_header(true)
21
-
22
- expect(name).to eq(ClearSiteData::HEADER_NAME)
23
- expect(value).to eq(
24
- %("cache", "cookies", "storage", "executionContexts")
25
- )
26
- end
27
-
28
- it "returns specified types" do
29
- name, value = described_class.make_header(["foo", "bar"])
30
-
31
- expect(name).to eq(ClearSiteData::HEADER_NAME)
32
- expect(value).to eq(%("foo", "bar"))
33
- end
34
- end
35
-
36
- describe "validate_config!" do
37
- it "succeeds for `true` config" do
38
- expect do
39
- described_class.validate_config!(true)
40
- end.not_to raise_error
41
- end
42
-
43
- it "succeeds for `nil` config" do
44
- expect do
45
- described_class.validate_config!(nil)
46
- end.not_to raise_error
47
- end
48
-
49
- it "succeeds for opt-out config" do
50
- expect do
51
- described_class.validate_config!(OPT_OUT)
52
- end.not_to raise_error
53
- end
54
-
55
- it "succeeds for empty config" do
56
- expect do
57
- described_class.validate_config!([])
58
- end.not_to raise_error
59
- end
60
-
61
- it "succeeds for Array of Strings config" do
62
- expect do
63
- described_class.validate_config!(["foo"])
64
- end.not_to raise_error
65
- end
66
-
67
- it "fails for Array of non-String config" do
68
- expect do
69
- described_class.validate_config!([1])
70
- end.to raise_error(ClearSiteDataConfigError)
71
- end
72
-
73
- it "fails for other types of config" do
74
- expect do
75
- described_class.validate_config!(:cookies)
76
- end.to raise_error(ClearSiteDataConfigError)
77
- end
78
- end
79
-
80
- describe "make_header_value" do
81
- it "returns a string of quoted values that are comma separated" do
82
- value = described_class.make_header_value(["foo", "bar"])
83
- expect(value).to eq(%("foo", "bar"))
84
- end
85
- end
86
- end
87
- end
@@ -1,215 +0,0 @@
1
- # frozen_string_literal: true
2
- require "spec_helper"
3
-
4
- module SecureHeaders
5
- describe ContentSecurityPolicy do
6
- let (:default_opts) do
7
- {
8
- default_src: %w(https:),
9
- img_src: %w(https: data:),
10
- script_src: %w('unsafe-inline' 'unsafe-eval' https: data:),
11
- style_src: %w('unsafe-inline' https: about:),
12
- report_uri: %w(/csp_report)
13
- }
14
- end
15
-
16
- describe "#name" do
17
- context "when in report-only mode" do
18
- specify { expect(ContentSecurityPolicy.new(default_opts.merge(report_only: true)).name).to eq(ContentSecurityPolicyReportOnlyConfig::HEADER_NAME) }
19
- end
20
-
21
- context "when in enforce mode" do
22
- specify { expect(ContentSecurityPolicy.new(default_opts).name).to eq(ContentSecurityPolicyConfig::HEADER_NAME) }
23
- end
24
- end
25
-
26
- describe "#value" do
27
- it "uses a safe but non-breaking default value" do
28
- expect(ContentSecurityPolicy.new.value).to eq("default-src https:; form-action 'self'; img-src https: data: 'self'; object-src 'none'; script-src https:; style-src 'self' 'unsafe-inline' https:")
29
- end
30
-
31
- it "deprecates and escapes semicolons in directive source lists" do
32
- expect(Kernel).to receive(:warn).with(%(frame_ancestors contains a ; in "google.com;script-src *;.;" which will raise an error in future versions. It has been replaced with a blank space.))
33
- expect(ContentSecurityPolicy.new(frame_ancestors: %w(https://google.com;script-src https://*;.;)).value).to eq("frame-ancestors google.com script-src * .")
34
- end
35
-
36
- it "deprecates and escapes semicolons in directive source lists" do
37
- expect(Kernel).to receive(:warn).with(%(frame_ancestors contains a \n in "\\nfoo.com\\nhacked" which will raise an error in future versions. It has been replaced with a blank space.))
38
- expect(ContentSecurityPolicy.new(frame_ancestors: ["\nfoo.com\nhacked"]).value).to eq("frame-ancestors foo.com hacked")
39
- end
40
-
41
- it "discards 'none' values if any other source expressions are present" do
42
- csp = ContentSecurityPolicy.new(default_opts.merge(child_src: %w('self' 'none')))
43
- expect(csp.value).not_to include("'none'")
44
- end
45
-
46
- it "discards source expressions (besides unsafe-* and non-host source values) when * is present" do
47
- csp = ContentSecurityPolicy.new(default_src: %w(* 'unsafe-inline' 'unsafe-eval' http: https: example.org data: blob:))
48
- expect(csp.value).to eq("default-src * 'unsafe-inline' 'unsafe-eval' data: blob:")
49
- end
50
-
51
- it "does not minify source expressions based on overlapping wildcards" do
52
- config = {
53
- default_src: %w(a.example.org b.example.org *.example.org https://*.example.org)
54
- }
55
- csp = ContentSecurityPolicy.new(config)
56
- expect(csp.value).to eq("default-src a.example.org b.example.org *.example.org")
57
- end
58
-
59
- it "removes http/s schemes from hosts" do
60
- csp = ContentSecurityPolicy.new(default_src: %w(https://example.org))
61
- expect(csp.value).to eq("default-src example.org")
62
- end
63
-
64
- it "does not build directives with a value of OPT_OUT (and bypasses directive requirements)" do
65
- csp = ContentSecurityPolicy.new(default_src: %w(https://example.org), script_src: OPT_OUT)
66
- expect(csp.value).to eq("default-src example.org")
67
- end
68
-
69
- it "does not remove schemes from report-uri values" do
70
- csp = ContentSecurityPolicy.new(default_src: %w(https:), report_uri: %w(https://example.org))
71
- expect(csp.value).to eq("default-src https:; report-uri https://example.org")
72
- end
73
-
74
- it "does not remove schemes when :preserve_schemes is true" do
75
- csp = ContentSecurityPolicy.new(default_src: %w(https://example.org), preserve_schemes: true)
76
- expect(csp.value).to eq("default-src https://example.org")
77
- end
78
-
79
- it "removes nil from source lists" do
80
- csp = ContentSecurityPolicy.new(default_src: ["https://example.org", nil])
81
- expect(csp.value).to eq("default-src example.org")
82
- end
83
-
84
- it "does not add a directive if the value is an empty array (or all nil)" do
85
- csp = ContentSecurityPolicy.new(default_src: ["https://example.org"], script_src: [nil])
86
- expect(csp.value).to eq("default-src example.org")
87
- end
88
-
89
- it "does not add a directive if the value is nil" do
90
- csp = ContentSecurityPolicy.new(default_src: ["https://example.org"], script_src: nil)
91
- expect(csp.value).to eq("default-src example.org")
92
- end
93
-
94
- it "does add a boolean directive if the value is true" do
95
- csp = ContentSecurityPolicy.new(default_src: ["https://example.org"], upgrade_insecure_requests: true)
96
- expect(csp.value).to eq("default-src example.org; upgrade-insecure-requests")
97
- end
98
-
99
- it "does not add a boolean directive if the value is false" do
100
- csp = ContentSecurityPolicy.new(default_src: ["https://example.org"], upgrade_insecure_requests: false)
101
- expect(csp.value).to eq("default-src example.org")
102
- end
103
-
104
- it "handles wildcard subdomain with wildcard port" do
105
- csp = ContentSecurityPolicy.new(default_src: %w(https://*.example.org:*))
106
- expect(csp.value).to eq("default-src *.example.org:*")
107
- end
108
-
109
- it "deduplicates source expressions that match exactly (after scheme stripping)" do
110
- csp = ContentSecurityPolicy.new(default_src: %w(example.org https://example.org example.org))
111
- expect(csp.value).to eq("default-src example.org")
112
- end
113
-
114
- it "does not deduplicate non-matching schema source expressions" do
115
- csp = ContentSecurityPolicy.new(default_src: %w(*.example.org wss://example.example.org))
116
- expect(csp.value).to eq("default-src *.example.org wss://example.example.org")
117
- end
118
-
119
- it "creates maximally strict sandbox policy when passed no sandbox token values" do
120
- csp = ContentSecurityPolicy.new(default_src: %w(example.org), sandbox: [])
121
- expect(csp.value).to eq("default-src example.org; sandbox")
122
- end
123
-
124
- it "creates maximally strict sandbox policy when passed true" do
125
- csp = ContentSecurityPolicy.new(default_src: %w(example.org), sandbox: true)
126
- expect(csp.value).to eq("default-src example.org; sandbox")
127
- end
128
-
129
- it "creates sandbox policy when passed valid sandbox token values" do
130
- csp = ContentSecurityPolicy.new(default_src: %w(example.org), sandbox: %w(allow-forms allow-scripts))
131
- expect(csp.value).to eq("default-src example.org; sandbox allow-forms allow-scripts")
132
- end
133
-
134
- it "does not emit a warning when using frame-src" do
135
- expect(Kernel).to_not receive(:warn)
136
- ContentSecurityPolicy.new(default_src: %w('self'), frame_src: %w('self')).value
137
- end
138
-
139
- it "allows script as a require-sri-src" do
140
- csp = ContentSecurityPolicy.new(default_src: %w('self'), require_sri_for: %w(script))
141
- expect(csp.value).to eq("default-src 'self'; require-sri-for script")
142
- end
143
-
144
- it "allows style as a require-sri-src" do
145
- csp = ContentSecurityPolicy.new(default_src: %w('self'), require_sri_for: %w(style))
146
- expect(csp.value).to eq("default-src 'self'; require-sri-for style")
147
- end
148
-
149
- it "allows script and style as a require-sri-src" do
150
- csp = ContentSecurityPolicy.new(default_src: %w('self'), require_sri_for: %w(script style))
151
- expect(csp.value).to eq("default-src 'self'; require-sri-for script style")
152
- end
153
-
154
- it "allows style as a require-trusted-types-for source" do
155
- csp = ContentSecurityPolicy.new(default_src: %w('self'), require_trusted_types_for: %w(script))
156
- expect(csp.value).to eq("default-src 'self'; require-trusted-types-for script")
157
- end
158
-
159
- it "includes prefetch-src" do
160
- csp = ContentSecurityPolicy.new(default_src: %w('self'), prefetch_src: %w(foo.com))
161
- expect(csp.value).to eq("default-src 'self'; prefetch-src foo.com")
162
- end
163
-
164
- it "includes navigate-to" do
165
- csp = ContentSecurityPolicy.new(default_src: %w('self'), navigate_to: %w(foo.com))
166
- expect(csp.value).to eq("default-src 'self'; navigate-to foo.com")
167
- end
168
-
169
- it "supports strict-dynamic" do
170
- csp = ContentSecurityPolicy.new({default_src: %w('self'), script_src: [ContentSecurityPolicy::STRICT_DYNAMIC], script_nonce: 123456})
171
- expect(csp.value).to eq("default-src 'self'; script-src 'strict-dynamic' 'nonce-123456' 'unsafe-inline'")
172
- end
173
-
174
- it "supports strict-dynamic and opting out of the appended 'unsafe-inline'" do
175
- csp = ContentSecurityPolicy.new({default_src: %w('self'), script_src: [ContentSecurityPolicy::STRICT_DYNAMIC], script_nonce: 123456, disable_nonce_backwards_compatibility: true })
176
- expect(csp.value).to eq("default-src 'self'; script-src 'strict-dynamic' 'nonce-123456'")
177
- end
178
-
179
- it "supports script-src-elem directive" do
180
- csp = ContentSecurityPolicy.new({script_src: %w('self'), script_src_elem: %w('self')})
181
- expect(csp.value).to eq("script-src 'self'; script-src-elem 'self'")
182
- end
183
-
184
- it "supports script-src-attr directive" do
185
- csp = ContentSecurityPolicy.new({script_src: %w('self'), script_src_attr: %w('self')})
186
- expect(csp.value).to eq("script-src 'self'; script-src-attr 'self'")
187
- end
188
-
189
- it "supports style-src-elem directive" do
190
- csp = ContentSecurityPolicy.new({style_src: %w('self'), style_src_elem: %w('self')})
191
- expect(csp.value).to eq("style-src 'self'; style-src-elem 'self'")
192
- end
193
-
194
- it "supports style-src-attr directive" do
195
- csp = ContentSecurityPolicy.new({style_src: %w('self'), style_src_attr: %w('self')})
196
- expect(csp.value).to eq("style-src 'self'; style-src-attr 'self'")
197
- end
198
-
199
- it "supports trusted-types directive" do
200
- csp = ContentSecurityPolicy.new({trusted_types: %w(blahblahpolicy)})
201
- expect(csp.value).to eq("trusted-types blahblahpolicy")
202
- end
203
-
204
- it "supports trusted-types directive with 'none'" do
205
- csp = ContentSecurityPolicy.new({trusted_types: %w('none')})
206
- expect(csp.value).to eq("trusted-types 'none'")
207
- end
208
-
209
- it "allows duplicate policy names in trusted-types directive" do
210
- csp = ContentSecurityPolicy.new({trusted_types: %w(blahblahpolicy 'allow-duplicates')})
211
- expect(csp.value).to eq("trusted-types blahblahpolicy 'allow-duplicates'")
212
- end
213
- end
214
- end
215
- end
@@ -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