rack-protection 2.0.0 → 2.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 60b24d006884c214484d2d6275ddfd9a09719fe6
4
- data.tar.gz: b43b08983d4fc1fcf5525d28e0b704e49ee93a25
2
+ SHA256:
3
+ metadata.gz: fa9d7fd8b6dd44cfd54fd833a1679efedfccdf76619d0b01e0aa2057f2e8b586
4
+ data.tar.gz: f0541b4bf7e3cc865bdca886de807968787e90a26ca4fcd3ff3787496e64a9de
5
5
  SHA512:
6
- metadata.gz: 926c434a0da749f9e615786c4600d7f3a933454ba179b4f3671d3abeb65d843281b95038258edaac3f01ae447c032aa8844141de0a399fd5447e6cbab12deac6
7
- data.tar.gz: 64892fdb92b20c537ffebbbc00d374e4d0bd07cf37dab25c21c95676b371477356c7ba3a52945e0f9a84b0db40bbd3fc964aa21a8525ed2bfac4dd3be204817f
6
+ metadata.gz: 89f4d7bd2b9ee4a1e51fb9a7d9699f0d1d3881a82bb3b8813527f6ce8cce96274462fd502e8df4d5f6b21cbf2d79da9bd69bff6a4e6e7e289e69aa7cb4e18893
7
+ data.tar.gz: 381cdab10dffb59181caef1a80b46e9d584e1f20fa602843f1649164bbd16d44cbfd5ba5aef2ebd0a447e52fad7437644d29188e98b9998a19a4377abbc0051f
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source "http://rubygems.org"
1
+ source "https://rubygems.org"
2
2
  # encoding: utf-8
3
3
 
4
4
  gem 'rake'
data/README.md CHANGED
@@ -1,7 +1,5 @@
1
1
  # Rack::Protection
2
2
 
3
- [![Build Status](https://secure.travis-ci.org/sinatra/rack-protection.png)](http://travis-ci.org/sinatra/rack-protection)
4
-
5
3
  This gem protects against typical web attacks.
6
4
  Should work for all Rack apps, including Rails.
7
5
 
@@ -40,55 +38,55 @@ run MyApp
40
38
 
41
39
  Prevented by:
42
40
 
43
- * `Rack::Protection::AuthenticityToken` (not included by `use Rack::Protection`)
44
- * `Rack::Protection::FormToken` (not included by `use Rack::Protection`)
45
- * `Rack::Protection::JsonCsrf`
46
- * `Rack::Protection::RemoteReferrer` (not included by `use Rack::Protection`)
47
- * `Rack::Protection::RemoteToken`
48
- * `Rack::Protection::HttpOrigin`
41
+ * [`Rack::Protection::AuthenticityToken`][authenticity-token] (not included by `use Rack::Protection`)
42
+ * [`Rack::Protection::FormToken`][form-token] (not included by `use Rack::Protection`)
43
+ * [`Rack::Protection::JsonCsrf`][json-csrf]
44
+ * [`Rack::Protection::RemoteReferrer`][remote-referrer] (not included by `use Rack::Protection`)
45
+ * [`Rack::Protection::RemoteToken`][remote-token]
46
+ * [`Rack::Protection::HttpOrigin`][http-origin]
49
47
 
50
48
  ## Cross Site Scripting
51
49
 
52
50
  Prevented by:
53
51
 
54
- * `Rack::Protection::EscapedParams` (not included by `use Rack::Protection`)
55
- * `Rack::Protection::XSSHeader` (Internet Explorer and Chrome only)
56
- * `Rack::Protection::ContentSecurityPolicy`
52
+ * [`Rack::Protection::EscapedParams`][escaped-params] (not included by `use Rack::Protection`)
53
+ * [`Rack::Protection::XSSHeader`][xss-header] (Internet Explorer and Chrome only)
54
+ * [`Rack::Protection::ContentSecurityPolicy`][content-security-policy]
57
55
 
58
56
  ## Clickjacking
59
57
 
60
58
  Prevented by:
61
59
 
62
- * `Rack::Protection::FrameOptions`
60
+ * [`Rack::Protection::FrameOptions`][frame-options]
63
61
 
64
62
  ## Directory Traversal
65
63
 
66
64
  Prevented by:
67
65
 
68
- * `Rack::Protection::PathTraversal`
66
+ * [`Rack::Protection::PathTraversal`][path-traversal]
69
67
 
70
68
  ## Session Hijacking
71
69
 
72
70
  Prevented by:
73
71
 
74
- * `Rack::Protection::SessionHijacking`
72
+ * [`Rack::Protection::SessionHijacking`][session-hijacking]
75
73
 
76
74
  ## Cookie Tossing
77
75
 
78
76
  Prevented by:
79
- * `Rack::Protection::CookieTossing` (not included by `use Rack::Protection`)
77
+ * [`Rack::Protection::CookieTossing`][cookie-tossing] (not included by `use Rack::Protection`)
80
78
 
81
79
  ## IP Spoofing
82
80
 
83
81
  Prevented by:
84
82
 
85
- * `Rack::Protection::IPSpoofing`
83
+ * [`Rack::Protection::IPSpoofing`][ip-spoofing]
86
84
 
87
85
  ## Helps to protect against protocol downgrade attacks and cookie hijacking
88
86
 
89
87
  Prevented by:
90
88
 
91
- * `Rack::Protection::StrictTransport` (not included by `use Rack::Protection`)
89
+ * [`Rack::Protection::StrictTransport`][strict-transport] (not included by `use Rack::Protection`)
92
90
 
93
91
  # Installation
94
92
 
@@ -102,3 +100,19 @@ use Rack::Protection, instrumenter: ActiveSupport::Notifications
102
100
  ```
103
101
 
104
102
  The instrumenter is passed a namespace (String) and environment (Hash). The namespace is 'rack.protection' and the attack type can be obtained from the environment key 'rack.protection.attack'.
103
+
104
+ [authenticity-token]: http://www.sinatrarb.com/protection/authenticity_token
105
+ [content-security-policy]: http://www.sinatrarb.com/protection/content_security_policy
106
+ [cookie-tossing]: http://www.sinatrarb.com/protection/cookie_tossing
107
+ [escaped-params]: http://www.sinatrarb.com/protection/escaped_params
108
+ [form-token]: http://www.sinatrarb.com/protection/form_token
109
+ [frame-options]: http://www.sinatrarb.com/protection/frame_options
110
+ [http-origin]: http://www.sinatrarb.com/protection/http_origin
111
+ [ip-spoofing]: http://www.sinatrarb.com/protection/ip_spoofing
112
+ [json-csrf]: http://www.sinatrarb.com/protection/json_csrf
113
+ [path-traversal]: http://www.sinatrarb.com/protection/path_traversal
114
+ [remote-referrer]: http://www.sinatrarb.com/protection/remote_referrer
115
+ [remote-token]: http://www.sinatrarb.com/protection/remote_token
116
+ [session-hijacking]: http://www.sinatrarb.com/protection/session_hijacking
117
+ [strict-transport]: http://www.sinatrarb.com/protection/strict_transport
118
+ [xss-header]: http://www.sinatrarb.com/protection/xss_header
data/Rakefile CHANGED
@@ -24,7 +24,15 @@ namespace :doc do
24
24
  end
25
25
  end
26
26
 
27
- task :all => [:readmes]
27
+ task :index do
28
+ doc = File.read("README.md")
29
+ file = "doc/rack-protection-readme.md"
30
+ Dir.mkdir "doc" unless File.directory? "doc"
31
+ puts "writing #{file}"
32
+ File.open(file, "w") { |f| f << doc }
33
+ end
34
+
35
+ task :all => [:readmes, :index]
28
36
  end
29
37
 
30
38
  desc "generate documentation"
@@ -1,5 +1,6 @@
1
1
  require 'rack/protection'
2
2
  require 'securerandom'
3
+ require 'openssl'
3
4
  require 'base64'
4
5
 
5
6
  module Rack
@@ -9,54 +10,140 @@ module Rack
9
10
  # Supported browsers:: all
10
11
  # More infos:: http://en.wikipedia.org/wiki/Cross-site_request_forgery
11
12
  #
12
- # Only accepts unsafe HTTP requests if a given access token matches the token
13
- # included in the session.
13
+ # This middleware only accepts requests other than <tt>GET</tt>,
14
+ # <tt>HEAD</tt>, <tt>OPTIONS</tt>, <tt>TRACE</tt> if their given access
15
+ # token matches the token included in the session.
14
16
  #
15
- # Compatible with rack-csrf.
17
+ # It checks the <tt>X-CSRF-Token</tt> header and the <tt>POST</tt> form
18
+ # data.
16
19
  #
17
- # Options:
20
+ # Compatible with the {rack-csrf}[https://rubygems.org/gems/rack_csrf] gem.
18
21
  #
19
- # authenticity_param: Defines the param's name that should contain the token on a request.
22
+ # == Options
23
+ #
24
+ # [<tt>:authenticity_param</tt>] the name of the param that should contain
25
+ # the token on a request. Default value:
26
+ # <tt>"authenticity_token"</tt>
27
+ #
28
+ # [<tt>:key</tt>] the name of the param that should contain
29
+ # the token in the session. Default value:
30
+ # <tt>:csrf</tt>
31
+ #
32
+ # [<tt>:allow_if</tt>] a proc for custom allow/deny logic. Default value:
33
+ # <tt>nil</tt>
34
+ #
35
+ # == Example: Forms application
36
+ #
37
+ # To show what the AuthenticityToken does, this section includes a sample
38
+ # program which shows two forms. One with, and one without a CSRF token
39
+ # The one without CSRF token field will get a 403 Forbidden response.
40
+ #
41
+ # Install the gem, then run the program:
42
+ #
43
+ # gem install 'rack-protection'
44
+ # ruby server.rb
45
+ #
46
+ # Here is <tt>server.rb</tt>:
47
+ #
48
+ # require 'rack/protection'
49
+ #
50
+ # app = Rack::Builder.app do
51
+ # use Rack::Session::Cookie, secret: 'secret'
52
+ # use Rack::Protection::AuthenticityToken
53
+ #
54
+ # run -> (env) do
55
+ # [200, {}, [
56
+ # <<~EOS
57
+ # <!DOCTYPE html>
58
+ # <html lang="en">
59
+ # <head>
60
+ # <meta charset="UTF-8" />
61
+ # <title>rack-protection minimal example</title>
62
+ # </head>
63
+ # <body>
64
+ # <h1>Without Authenticity Token</h1>
65
+ # <p>This takes you to <tt>Forbidden</tt></p>
66
+ # <form action="" method="post">
67
+ # <input type="text" name="foo" />
68
+ # <input type="submit" />
69
+ # </form>
70
+ #
71
+ # <h1>With Authenticity Token</h1>
72
+ # <p>This successfully takes you to back to this form.</p>
73
+ # <form action="" method="post">
74
+ # <input type="hidden" name="authenticity_token" value="#{Rack::Protection::AuthenticityToken.token(env['rack.session'])}" />
75
+ # <input type="text" name="foo" />
76
+ # <input type="submit" />
77
+ # </form>
78
+ # </body>
79
+ # </html>
80
+ # EOS
81
+ # ]]
82
+ # end
83
+ # end
84
+ #
85
+ # Rack::Handler::WEBrick.run app
86
+ #
87
+ # == Example: Customize which POST parameter holds the token
88
+ #
89
+ # To customize the authenticity parameter for form data, use the
90
+ # <tt>:authenticity_param</tt> option:
91
+ # use Rack::Protection::AuthenticityToken, authenticity_param: 'your_token_param_name'
20
92
  class AuthenticityToken < Base
21
93
  TOKEN_LENGTH = 32
22
94
 
23
95
  default_options :authenticity_param => 'authenticity_token',
96
+ :key => :csrf,
24
97
  :allow_if => nil
25
98
 
26
- def self.token(session)
27
- self.new(nil).mask_authenticity_token(session)
99
+ def self.token(session, path: nil, method: :post)
100
+ self.new(nil).mask_authenticity_token(session, path: path, method: method)
28
101
  end
29
102
 
30
103
  def self.random_token
31
- SecureRandom.base64(TOKEN_LENGTH)
104
+ SecureRandom.urlsafe_base64(TOKEN_LENGTH, padding: false)
32
105
  end
33
106
 
34
107
  def accepts?(env)
35
- session = session env
108
+ session = session(env)
36
109
  set_token(session)
37
110
 
38
111
  safe?(env) ||
39
- valid_token?(session, env['HTTP_X_CSRF_TOKEN']) ||
40
- valid_token?(session, Request.new(env).params[options[:authenticity_param]]) ||
112
+ valid_token?(env, env['HTTP_X_CSRF_TOKEN']) ||
113
+ valid_token?(env, Request.new(env).params[options[:authenticity_param]]) ||
41
114
  ( options[:allow_if] && options[:allow_if].call(env) )
115
+ rescue
116
+ false
42
117
  end
43
118
 
44
- def mask_authenticity_token(session)
45
- token = set_token(session)
119
+ def mask_authenticity_token(session, path: nil, method: :post)
120
+ set_token(session)
121
+
122
+ token = if path && method
123
+ per_form_token(session, path, method)
124
+ else
125
+ global_token(session)
126
+ end
127
+
46
128
  mask_token(token)
47
129
  end
48
130
 
131
+ GLOBAL_TOKEN_IDENTIFIER = '!real_csrf_token'
132
+ private_constant :GLOBAL_TOKEN_IDENTIFIER
133
+
49
134
  private
50
135
 
51
136
  def set_token(session)
52
- session[:csrf] ||= self.class.random_token
137
+ session[options[:key]] ||= self.class.random_token
53
138
  end
54
139
 
55
140
  # Checks the client's masked token to see if it matches the
56
141
  # session token.
57
- def valid_token?(session, token)
142
+ def valid_token?(env, token)
58
143
  return false if token.nil? || token.empty?
59
144
 
145
+ session = session(env)
146
+
60
147
  begin
61
148
  token = decode_token(token)
62
149
  rescue ArgumentError # encoded_masked_token is invalid Base64
@@ -67,13 +154,13 @@ module Rack
67
154
  # to handle any unmasked tokens that we've issued without error.
68
155
 
69
156
  if unmasked_token?(token)
70
- compare_with_real_token token, session
71
-
157
+ compare_with_real_token(token, session)
72
158
  elsif masked_token?(token)
73
159
  token = unmask_token(token)
74
160
 
75
- compare_with_real_token token, session
76
-
161
+ compare_with_global_token(token, session) ||
162
+ compare_with_real_token(token, session) ||
163
+ compare_with_per_form_token(token, session, Request.new(env))
77
164
  else
78
165
  false # Token is malformed
79
166
  end
@@ -83,7 +170,6 @@ module Rack
83
170
  # on each request. The masking is used to mitigate SSL attacks
84
171
  # like BREACH.
85
172
  def mask_token(token)
86
- token = decode_token(token)
87
173
  one_time_pad = SecureRandom.random_bytes(token.length)
88
174
  encrypted_token = xor_byte_strings(one_time_pad, token)
89
175
  masked_token = one_time_pad + encrypted_token
@@ -112,20 +198,53 @@ module Rack
112
198
  secure_compare(token, real_token(session))
113
199
  end
114
200
 
201
+ def compare_with_global_token(token, session)
202
+ secure_compare(token, global_token(session))
203
+ end
204
+
205
+ def compare_with_per_form_token(token, session, request)
206
+ secure_compare(token,
207
+ per_form_token(session, request.path.chomp('/'), request.request_method)
208
+ )
209
+ end
210
+
115
211
  def real_token(session)
116
- decode_token(session[:csrf])
212
+ decode_token(session[options[:key]])
213
+ end
214
+
215
+ def global_token(session)
216
+ token_hmac(session, GLOBAL_TOKEN_IDENTIFIER)
217
+ end
218
+
219
+ def per_form_token(session, path, method)
220
+ token_hmac(session, "#{path}##{method.downcase}")
117
221
  end
118
222
 
119
223
  def encode_token(token)
120
- Base64.strict_encode64(token)
224
+ Base64.urlsafe_encode64(token)
121
225
  end
122
226
 
123
227
  def decode_token(token)
124
- Base64.strict_decode64(token)
228
+ Base64.urlsafe_decode64(token)
229
+ end
230
+
231
+ def token_hmac(session, identifier)
232
+ OpenSSL::HMAC.digest(
233
+ OpenSSL::Digest::SHA256.new,
234
+ real_token(session),
235
+ identifier
236
+ )
125
237
  end
126
238
 
127
239
  def xor_byte_strings(s1, s2)
128
- s1.bytes.zip(s2.bytes).map { |(c1,c2)| c1 ^ c2 }.pack('c*')
240
+ s2 = s2.dup
241
+ size = s1.bytesize
242
+ i = 0
243
+ while i < size
244
+ s2.setbyte(i, s1.getbyte(i) ^ s2.getbyte(i))
245
+ i += 1
246
+ end
247
+ s2
129
248
  end
130
249
  end
131
250
  end
@@ -13,7 +13,7 @@ module Rack
13
13
  :session_key => 'rack.session', :status => 403,
14
14
  :allow_empty_referrer => true,
15
15
  :report_key => "protection.failed",
16
- :html_types => %w[text/html application/xhtml]
16
+ :html_types => %w[text/html application/xhtml text/xml application/xml]
17
17
  }
18
18
 
19
19
  attr_reader :app, :options
@@ -36,16 +36,15 @@ module Rack
36
36
  # to be used in a policy.
37
37
  #
38
38
  class ContentSecurityPolicy < Base
39
- default_options default_src: :none, script_src: "'self'",
40
- img_src: "'self'", style_src: "'self'",
41
- connect_src: "'self'", report_only: false
39
+ default_options default_src: "'self'", report_only: false
42
40
 
43
41
  DIRECTIVES = %i(base_uri child_src connect_src default_src
44
42
  font_src form_action frame_ancestors frame_src
45
43
  img_src manifest_src media_src object_src
46
44
  plugin_types referrer reflected_xss report_to
47
45
  report_uri require_sri_for sandbox script_src
48
- style_src worker_src).freeze
46
+ style_src worker_src webrtc_src navigate_to
47
+ prefetch_src).freeze
49
48
 
50
49
  NO_ARG_DIRECTIVES = %i(block_all_mixed_content disown_opener
51
50
  upgrade_insecure_requests).freeze
@@ -62,7 +61,7 @@ module Rack
62
61
  # Set these key values to boolean 'true' to include in policy
63
62
  NO_ARG_DIRECTIVES.each do |d|
64
63
  if options.key?(d) && options[d].is_a?(TrueClass)
65
- directives << d.to_s.sub(/_/, '-')
64
+ directives << d.to_s.tr('_', '-')
66
65
  end
67
66
  end
68
67
 
@@ -9,11 +9,11 @@ module Rack
9
9
  # http://tools.ietf.org/html/draft-abarth-origin
10
10
  #
11
11
  # Does not accept unsafe HTTP requests when value of Origin HTTP request header
12
- # does not match default or whitelisted URIs.
12
+ # does not match default or permitted URIs.
13
13
  #
14
- # If you want to whitelist a specific domain, you can pass in as the `:origin_whitelist` option:
14
+ # If you want to permit a specific domain, you can pass in as the `:permitted_origins` option:
15
15
  #
16
- # use Rack::Protection, origin_whitelist: ["http://localhost:3000", "http://127.0.01:3000"]
16
+ # use Rack::Protection, permitted_origins: ["http://localhost:3000", "http://127.0.01:3000"]
17
17
  #
18
18
  # The `:allow_if` option can also be set to a proc to use custom allow/deny logic.
19
19
  class HttpOrigin < Base
@@ -32,7 +32,14 @@ module Rack
32
32
  return true unless origin = env['HTTP_ORIGIN']
33
33
  return true if base_url(env) == origin
34
34
  return true if options[:allow_if] && options[:allow_if].call(env)
35
- Array(options[:origin_whitelist]).include? origin
35
+
36
+ if options.key? :origin_whitelist
37
+ warn env, "Rack::Protection origin_whitelist option is deprecated and will be removed, " \
38
+ "use permitted_origins instead.\n"
39
+ end
40
+
41
+ permitted_origins = options[:permitted_origins] || options[:origin_whitelist]
42
+ Array(permitted_origins).include? origin
36
43
  end
37
44
 
38
45
  end
@@ -19,19 +19,14 @@ module Rack
19
19
  end
20
20
 
21
21
  def cleanup(path)
22
- if path.respond_to?(:encoding)
23
- # Ruby 1.9+ M17N
24
- encoding = path.encoding
25
- dot = '.'.encode(encoding)
26
- slash = '/'.encode(encoding)
27
- else
28
- # Ruby 1.8
29
- dot = '.'
30
- slash = '/'
31
- end
22
+ encoding = path.encoding
23
+ dot = '.'.encode(encoding)
24
+ slash = '/'.encode(encoding)
25
+ backslash = '\\'.encode(encoding)
32
26
 
33
27
  parts = []
34
- unescaped = path.gsub(/%2e/i, dot).gsub(/%2f/i, slash)
28
+ unescaped = path.gsub(/%2e/i, dot).gsub(/%2f/i, slash).gsub(/%5c/i, backslash)
29
+ unescaped = unescaped.gsub(backslash, slash)
35
30
 
36
31
  unescaped.split(slash).each do |part|
37
32
  next if part.empty? or part == dot
@@ -0,0 +1,25 @@
1
+ require 'rack/protection'
2
+
3
+ module Rack
4
+ module Protection
5
+ ##
6
+ # Prevented attack:: Secret leakage, third party tracking
7
+ # Supported browsers:: mixed support
8
+ # More infos:: https://www.w3.org/TR/referrer-policy/
9
+ # https://caniuse.com/#search=referrer-policy
10
+ #
11
+ # Sets Referrer-Policy header to tell the browser to limit the Referer header.
12
+ #
13
+ # Options:
14
+ # referrer_policy:: The policy to use (default: 'strict-origin-when-cross-origin')
15
+ class ReferrerPolicy < Base
16
+ default_options :referrer_policy => 'strict-origin-when-cross-origin'
17
+
18
+ def call(env)
19
+ status, headers, body = @app.call(env)
20
+ headers['Referrer-Policy'] ||= options[:referrer_policy]
21
+ [status, headers, body]
22
+ end
23
+ end
24
+ end
25
+ end
@@ -14,7 +14,7 @@ module Rack
14
14
  class SessionHijacking < Base
15
15
  default_reaction :drop_session
16
16
  default_options :tracking_key => :tracking, :encrypt_tracking => true,
17
- :track => %w[HTTP_USER_AGENT HTTP_ACCEPT_LANGUAGE]
17
+ :track => %w[HTTP_USER_AGENT]
18
18
 
19
19
  def accepts?(env)
20
20
  session = session env
@@ -1,5 +1,5 @@
1
1
  module Rack
2
2
  module Protection
3
- VERSION = '2.0.0'
3
+ VERSION = '2.2.1'
4
4
  end
5
5
  end
@@ -14,6 +14,7 @@ module Rack
14
14
  autoload :IPSpoofing, 'rack/protection/ip_spoofing'
15
15
  autoload :JsonCsrf, 'rack/protection/json_csrf'
16
16
  autoload :PathTraversal, 'rack/protection/path_traversal'
17
+ autoload :ReferrerPolicy, 'rack/protection/referrer_policy'
17
18
  autoload :RemoteReferrer, 'rack/protection/remote_referrer'
18
19
  autoload :RemoteToken, 'rack/protection/remote_token'
19
20
  autoload :SessionHijacking, 'rack/protection/session_hijacking'
@@ -32,9 +33,11 @@ module Rack
32
33
  Rack::Builder.new do
33
34
  # Off by default, unless added
34
35
  use ::Rack::Protection::AuthenticityToken, options if use_these.include? :authenticity_token
35
- use ::Rack::Protection::CookieTossing, options if use_these.include? :cookie_tossing
36
36
  use ::Rack::Protection::ContentSecurityPolicy, options if use_these.include? :content_security_policy
37
+ use ::Rack::Protection::CookieTossing, options if use_these.include? :cookie_tossing
38
+ use ::Rack::Protection::EscapedParams, options if use_these.include? :escaped_params
37
39
  use ::Rack::Protection::FormToken, options if use_these.include? :form_token
40
+ use ::Rack::Protection::ReferrerPolicy, options if use_these.include? :referrer_policy
38
41
  use ::Rack::Protection::RemoteReferrer, options if use_these.include? :remote_referrer
39
42
  use ::Rack::Protection::StrictTransport, options if use_these.include? :strict_transport
40
43
 
@@ -5,7 +5,7 @@ Gem::Specification.new do |s|
5
5
  s.name = "rack-protection"
6
6
  s.version = version
7
7
  s.description = "Protect against typical web attacks, works with all Rack apps, including Rails."
8
- s.homepage = "http://github.com/sinatra/sinatra/tree/master/rack-protection"
8
+ s.homepage = "http://sinatrarb.com/protection/"
9
9
  s.summary = s.description
10
10
  s.license = 'MIT'
11
11
  s.authors = ["https://github.com/sinatra/sinatra/graphs/contributors"]
@@ -18,8 +18,23 @@ Gem::Specification.new do |s|
18
18
  "rack-protection.gemspec"
19
19
  ]
20
20
 
21
+ if s.respond_to?(:metadata)
22
+ s.metadata = {
23
+ 'source_code_uri' => 'https://github.com/sinatra/sinatra/tree/master/rack-protection',
24
+ 'homepage_uri' => 'http://sinatrarb.com/protection/',
25
+ 'documentation_uri' => 'https://www.rubydoc.info/gems/rack-protection'
26
+ }
27
+ else
28
+ raise <<-EOF
29
+ RubyGems 2.0 or newer is required to protect against public gem pushes. You can update your rubygems version by running:
30
+ gem install rubygems-update
31
+ update_rubygems:
32
+ gem update --system
33
+ EOF
34
+ end
35
+
21
36
  # dependencies
22
37
  s.add_dependency "rack"
23
38
  s.add_development_dependency "rack-test"
24
- s.add_development_dependency "rspec", "~> 3.0.0"
39
+ s.add_development_dependency "rspec", "~> 3.6"
25
40
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-protection
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - https://github.com/sinatra/sinatra/graphs/contributors
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-05-07 00:00:00.000000000 Z
11
+ date: 2022-07-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 3.0.0
47
+ version: '3.6'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 3.0.0
54
+ version: '3.6'
55
55
  description: Protect against typical web attacks, works with all Rack apps, including
56
56
  Rails.
57
57
  email: sinatrarb@googlegroups.com
@@ -76,6 +76,7 @@ files:
76
76
  - lib/rack/protection/ip_spoofing.rb
77
77
  - lib/rack/protection/json_csrf.rb
78
78
  - lib/rack/protection/path_traversal.rb
79
+ - lib/rack/protection/referrer_policy.rb
79
80
  - lib/rack/protection/remote_referrer.rb
80
81
  - lib/rack/protection/remote_token.rb
81
82
  - lib/rack/protection/session_hijacking.rb
@@ -83,11 +84,14 @@ files:
83
84
  - lib/rack/protection/version.rb
84
85
  - lib/rack/protection/xss_header.rb
85
86
  - rack-protection.gemspec
86
- homepage: http://github.com/sinatra/sinatra/tree/master/rack-protection
87
+ homepage: http://sinatrarb.com/protection/
87
88
  licenses:
88
89
  - MIT
89
- metadata: {}
90
- post_install_message:
90
+ metadata:
91
+ source_code_uri: https://github.com/sinatra/sinatra/tree/master/rack-protection
92
+ homepage_uri: http://sinatrarb.com/protection/
93
+ documentation_uri: https://www.rubydoc.info/gems/rack-protection
94
+ post_install_message:
91
95
  rdoc_options: []
92
96
  require_paths:
93
97
  - lib
@@ -102,9 +106,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
102
106
  - !ruby/object:Gem::Version
103
107
  version: '0'
104
108
  requirements: []
105
- rubyforge_project:
106
- rubygems_version: 2.6.11
107
- signing_key:
109
+ rubygems_version: 3.0.3.1
110
+ signing_key:
108
111
  specification_version: 4
109
112
  summary: Protect against typical web attacks, works with all Rack apps, including
110
113
  Rails.