secure_headers 3.7.0 → 4.0.0.alpha01

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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +1 -0
  3. data/.rubocop.yml +3 -0
  4. data/.ruby-version +1 -1
  5. data/.travis.yml +8 -6
  6. data/CHANGELOG.md +2 -10
  7. data/CONTRIBUTING.md +1 -1
  8. data/Gemfile +7 -4
  9. data/Guardfile +1 -0
  10. data/README.md +4 -24
  11. data/Rakefile +22 -18
  12. data/docs/cookies.md +16 -2
  13. data/lib/secure_headers/configuration.rb +6 -16
  14. data/lib/secure_headers/hash_helper.rb +2 -1
  15. data/lib/secure_headers/headers/clear_site_data.rb +2 -1
  16. data/lib/secure_headers/headers/content_security_policy.rb +7 -12
  17. data/lib/secure_headers/headers/content_security_policy_config.rb +1 -0
  18. data/lib/secure_headers/headers/cookie.rb +21 -3
  19. data/lib/secure_headers/headers/policy_management.rb +10 -2
  20. data/lib/secure_headers/headers/public_key_pins.rb +4 -3
  21. data/lib/secure_headers/headers/referrer_policy.rb +1 -0
  22. data/lib/secure_headers/headers/strict_transport_security.rb +2 -1
  23. data/lib/secure_headers/headers/x_content_type_options.rb +1 -0
  24. data/lib/secure_headers/headers/x_download_options.rb +2 -1
  25. data/lib/secure_headers/headers/x_frame_options.rb +1 -0
  26. data/lib/secure_headers/headers/x_permitted_cross_domain_policies.rb +2 -1
  27. data/lib/secure_headers/headers/x_xss_protection.rb +2 -1
  28. data/lib/secure_headers/middleware.rb +10 -9
  29. data/lib/secure_headers/railtie.rb +7 -6
  30. data/lib/secure_headers/utils/cookies_config.rb +13 -12
  31. data/lib/secure_headers/view_helper.rb +2 -1
  32. data/lib/secure_headers.rb +1 -2
  33. data/lib/tasks/tasks.rake +2 -1
  34. data/secure_headers.gemspec +13 -3
  35. data/spec/lib/secure_headers/configuration_spec.rb +9 -8
  36. data/spec/lib/secure_headers/headers/clear_site_data_spec.rb +2 -1
  37. data/spec/lib/secure_headers/headers/content_security_policy_spec.rb +11 -16
  38. data/spec/lib/secure_headers/headers/cookie_spec.rb +38 -20
  39. data/spec/lib/secure_headers/headers/policy_management_spec.rb +20 -10
  40. data/spec/lib/secure_headers/headers/public_key_pins_spec.rb +7 -6
  41. data/spec/lib/secure_headers/headers/referrer_policy_spec.rb +4 -3
  42. data/spec/lib/secure_headers/headers/strict_transport_security_spec.rb +5 -4
  43. data/spec/lib/secure_headers/headers/x_content_type_options_spec.rb +2 -1
  44. data/spec/lib/secure_headers/headers/x_download_options_spec.rb +3 -2
  45. data/spec/lib/secure_headers/headers/x_frame_options_spec.rb +2 -1
  46. data/spec/lib/secure_headers/headers/x_permitted_cross_domain_policies_spec.rb +4 -3
  47. data/spec/lib/secure_headers/headers/x_xss_protection_spec.rb +4 -3
  48. data/spec/lib/secure_headers/middleware_spec.rb +18 -21
  49. data/spec/lib/secure_headers/view_helpers_spec.rb +5 -4
  50. data/spec/lib/secure_headers_spec.rb +92 -120
  51. data/spec/spec_helper.rb +9 -23
  52. data/upgrading-to-4-0.md +49 -0
  53. metadata +15 -11
  54. data/lib/secure_headers/headers/expect_certificate_transparency.rb +0 -70
  55. data/spec/lib/secure_headers/headers/expect_certificate_spec.rb +0 -42
@@ -1,9 +1,10 @@
1
- require 'spec_helper'
1
+ # frozen_string_literal: true
2
+ require "spec_helper"
2
3
 
3
4
  module SecureHeaders
4
5
  describe XDownloadOptions do
5
6
  specify { expect(XDownloadOptions.make_header).to eq([XDownloadOptions::HEADER_NAME, XDownloadOptions::DEFAULT_VALUE]) }
6
- specify { expect(XDownloadOptions.make_header('noopen')).to eq([XDownloadOptions::HEADER_NAME, 'noopen']) }
7
+ specify { expect(XDownloadOptions.make_header("noopen")).to eq([XDownloadOptions::HEADER_NAME, "noopen"]) }
7
8
 
8
9
  context "invalid configuration values" do
9
10
  it "accepts noopen" do
@@ -1,4 +1,5 @@
1
- require 'spec_helper'
1
+ # frozen_string_literal: true
2
+ require "spec_helper"
2
3
 
3
4
  module SecureHeaders
4
5
  describe XFrameOptions do
@@ -1,9 +1,10 @@
1
- require 'spec_helper'
1
+ # frozen_string_literal: true
2
+ require "spec_helper"
2
3
 
3
4
  module SecureHeaders
4
5
  describe XPermittedCrossDomainPolicies do
5
6
  specify { expect(XPermittedCrossDomainPolicies.make_header).to eq([XPermittedCrossDomainPolicies::HEADER_NAME, "none"]) }
6
- specify { expect(XPermittedCrossDomainPolicies.make_header('master-only')).to eq([XPermittedCrossDomainPolicies::HEADER_NAME, 'master-only']) }
7
+ specify { expect(XPermittedCrossDomainPolicies.make_header("master-only")).to eq([XPermittedCrossDomainPolicies::HEADER_NAME, "master-only"]) }
7
8
 
8
9
  context "valid configuration values" do
9
10
  it "accepts 'all'" do
@@ -36,7 +37,7 @@ module SecureHeaders
36
37
  end
37
38
  end
38
39
 
39
- context 'invlaid configuration values' do
40
+ context "invlaid configuration values" do
40
41
  it "doesn't accept invalid values" do
41
42
  expect do
42
43
  XPermittedCrossDomainPolicies.validate_config!("open")
@@ -1,9 +1,10 @@
1
- require 'spec_helper'
1
+ # frozen_string_literal: true
2
+ require "spec_helper"
2
3
 
3
4
  module SecureHeaders
4
5
  describe XXssProtection do
5
6
  specify { expect(XXssProtection.make_header).to eq([XXssProtection::HEADER_NAME, XXssProtection::DEFAULT_VALUE]) }
6
- specify { expect(XXssProtection.make_header("1; mode=block; report=https://www.secure.com/reports")).to eq([XXssProtection::HEADER_NAME, '1; mode=block; report=https://www.secure.com/reports']) }
7
+ specify { expect(XXssProtection.make_header("1; mode=block; report=https://www.secure.com/reports")).to eq([XXssProtection::HEADER_NAME, "1; mode=block; report=https://www.secure.com/reports"]) }
7
8
 
8
9
  context "with invalid configuration" do
9
10
  it "should raise an error when providing a string that is not valid" do
@@ -19,7 +20,7 @@ module SecureHeaders
19
20
  context "when using a hash value" do
20
21
  it "should allow string values ('1' or '0' are the only valid strings)" do
21
22
  expect do
22
- XXssProtection.validate_config!('1')
23
+ XXssProtection.validate_config!("1")
23
24
  end.not_to raise_error
24
25
  end
25
26
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "spec_helper"
2
3
 
3
4
  module SecureHeaders
@@ -19,8 +20,8 @@ module SecureHeaders
19
20
  config.hpkp = {
20
21
  max_age: 10000000,
21
22
  pins: [
22
- {sha256: 'b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c'},
23
- {sha256: '73a2c64f9545172c1195efb6616ca5f7afd1df6f245407cafb90de3998a1c97f'}
23
+ {sha256: "b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c"},
24
+ {sha256: "73a2c64f9545172c1195efb6616ca5f7afd1df6f245407cafb90de3998a1c97f"}
24
25
  ],
25
26
  report_uri: "https://#{report_host}/example-hpkp"
26
27
  }
@@ -54,68 +55,64 @@ module SecureHeaders
54
55
  expect(env[ContentSecurityPolicyConfig::HEADER_NAME]).to match("example.org")
55
56
  end
56
57
 
57
- context "secure_cookies" do
58
+ context "cookies" do
58
59
  context "cookies should be flagged" do
59
60
  it "flags cookies as secure" do
60
- capture_warning do
61
- Configuration.default { |config| config.secure_cookies = true }
62
- end
61
+ Configuration.default { |config| config.cookies = {secure: true, httponly: OPT_OUT, samesite: OPT_OUT} }
63
62
  request = Rack::Request.new("HTTPS" => "on")
64
63
  _, env = cookie_middleware.call request.env
65
- expect(env['Set-Cookie']).to eq("foo=bar; secure")
64
+ expect(env["Set-Cookie"]).to eq("foo=bar; secure")
66
65
  end
67
66
  end
68
67
 
69
68
  context "cookies should not be flagged" do
70
69
  it "does not flags cookies as secure" do
71
- capture_warning do
72
- Configuration.default { |config| config.secure_cookies = false }
73
- end
70
+ Configuration.default { |config| config.cookies = {secure: OPT_OUT, httponly: OPT_OUT, samesite: OPT_OUT} }
74
71
  request = Rack::Request.new("HTTPS" => "on")
75
72
  _, env = cookie_middleware.call request.env
76
- expect(env['Set-Cookie']).to eq("foo=bar")
73
+ expect(env["Set-Cookie"]).to eq("foo=bar")
77
74
  end
78
75
  end
79
76
  end
80
77
 
81
78
  context "cookies" do
82
79
  it "flags cookies from configuration" do
83
- Configuration.default { |config| config.cookies = { secure: true, httponly: true } }
80
+ Configuration.default { |config| config.cookies = { secure: true, httponly: true, samesite: { lax: true} } }
84
81
  request = Rack::Request.new("HTTPS" => "on")
85
82
  _, env = cookie_middleware.call request.env
86
83
 
87
- expect(env['Set-Cookie']).to eq("foo=bar; secure; HttpOnly")
84
+ expect(env["Set-Cookie"]).to eq("foo=bar; secure; HttpOnly; SameSite=Lax")
88
85
  end
89
86
 
90
87
  it "flags cookies with a combination of SameSite configurations" do
91
88
  cookie_middleware = Middleware.new(lambda { |env| [200, env.merge("Set-Cookie" => ["_session=foobar", "_guest=true"]), "app"] })
92
89
 
93
- Configuration.default { |config| config.cookies = { samesite: { lax: { except: ["_session"] }, strict: { only: ["_session"] } } } }
90
+ Configuration.default { |config| config.cookies = { samesite: { lax: { except: ["_session"] }, strict: { only: ["_session"] } }, httponly: OPT_OUT, secure: OPT_OUT} }
94
91
  request = Rack::Request.new("HTTPS" => "on")
95
92
  _, env = cookie_middleware.call request.env
96
93
 
97
- expect(env['Set-Cookie']).to match("_session=foobar; SameSite=Strict")
98
- expect(env['Set-Cookie']).to match("_guest=true; SameSite=Lax")
94
+ expect(env["Set-Cookie"]).to match("_session=foobar; SameSite=Strict")
95
+ expect(env["Set-Cookie"]).to match("_guest=true; SameSite=Lax")
99
96
  end
100
97
 
101
98
  it "disables secure cookies for non-https requests" do
102
- Configuration.default { |config| config.cookies = { secure: true } }
99
+ Configuration.default { |config| config.cookies = { secure: true, httponly: OPT_OUT, samesite: OPT_OUT } }
103
100
 
104
101
  request = Rack::Request.new("HTTPS" => "off")
105
102
  _, env = cookie_middleware.call request.env
106
- expect(env['Set-Cookie']).to eq("foo=bar")
103
+ expect(env["Set-Cookie"]).to eq("foo=bar")
107
104
  end
108
105
 
109
106
  it "sets the secure cookie flag correctly on interleaved http/https requests" do
110
- Configuration.default { |config| config.cookies = { secure: true } }
107
+ Configuration.default { |config| config.cookies = { secure: true, httponly: OPT_OUT, samesite: OPT_OUT } }
111
108
 
112
109
  request = Rack::Request.new("HTTPS" => "off")
113
110
  _, env = cookie_middleware.call request.env
114
- expect(env['Set-Cookie']).to eq("foo=bar")
111
+ expect(env["Set-Cookie"]).to eq("foo=bar")
115
112
 
116
113
  request = Rack::Request.new("HTTPS" => "on")
117
114
  _, env = cookie_middleware.call request.env
118
- expect(env['Set-Cookie']).to eq("foo=bar; secure")
115
+ expect(env["Set-Cookie"]).to eq("foo=bar; secure")
119
116
  end
120
117
  end
121
118
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "spec_helper"
2
3
  require "erb"
3
4
 
@@ -58,7 +59,7 @@ TEMPLATE
58
59
  end
59
60
 
60
61
  if options.is_a?(Hash)
61
- options = options.map {|k,v| " #{k}=#{v}"}
62
+ options = options.map {|k, v| " #{k}=#{v}"}
62
63
  end
63
64
  "<#{type}#{options}>#{content}</#{type}>"
64
65
  end
@@ -82,9 +83,9 @@ module SecureHeaders
82
83
  before(:all) do
83
84
  Configuration.default do |config|
84
85
  config.csp = {
85
- :default_src => %w('self'),
86
- :script_src => %w('self'),
87
- :style_src => %w('self')
86
+ default_src: %w('self'),
87
+ script_src: %w('self'),
88
+ style_src: %w('self')
88
89
  }
89
90
  end
90
91
  end