actionpack 5.2.2 → 5.2.4.5

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fd5843c9358811347699b33aca9fda92ef89519a3b646a7b0a929a861d551094
4
- data.tar.gz: 82f76e74229c5e354ddfd3b5a3927e963a7d595f8a25ac28bb00c6f8c1f31e88
3
+ metadata.gz: 8458248b602da029b1e9113db9f0305888fdf99bf83ea4fe679ad0ed49b22175
4
+ data.tar.gz: '085825f1ed9d286aa92cf5fa06fb039534331030d5b70da304c237a492f7ded9'
5
5
  SHA512:
6
- metadata.gz: fcf7d3458044418701c2eea5514a798cfad685753a86c5ef042bd4e14466d6ccc2438f7720b7e5097c6b25e592503f941863e022b42f8b699a3c6a3b2cfc788d
7
- data.tar.gz: aa112bc8943117e78ee1326a72aa91e01b55928884305715d2fc80c2ee9c1a57cc2a49a56b140b37c1e22d92985675fbd9c6f944518ee80b7870075dce88b5ed
6
+ metadata.gz: 7a6b62b3afeeb992a981128fbfab64944e897f20a0e75cbef6fd3d972108321ff440f7344935c8d196c1d1e6d3e08d64f040c6c5aa9ad63f06e9b78875da0c54
7
+ data.tar.gz: 27a049710288451664d3672a6fb18fe505003d9bb91826408ab507d9de06fa9f1a877a2dfc6b9a9b91e32c0f122cdfd33b1bcd3802e64966e4388c17dcad08e6
data/CHANGELOG.md CHANGED
@@ -1,3 +1,57 @@
1
+ ## Rails 5.2.4.5 (February 10, 2021) ##
2
+
3
+ * No changes.
4
+
5
+
6
+ ## Rails 5.2.4.4 (September 09, 2020) ##
7
+
8
+ * No changes.
9
+
10
+
11
+ ## Rails 5.2.4.3 (May 18, 2020) ##
12
+
13
+ * [CVE-2020-8166] HMAC raw CSRF token before masking it, so it cannot be used to reconstruct a per-form token
14
+
15
+ * [CVE-2020-8164] Return self when calling #each, #each_pair, and #each_value instead of the raw @parameters hash
16
+
17
+
18
+ ## Rails 5.2.4.1 (December 18, 2019) ##
19
+
20
+ * Fix possible information leak / session hijacking vulnerability.
21
+
22
+ The `ActionDispatch::Session::MemcacheStore` is still vulnerable given it requires the
23
+ gem dalli to be updated as well.
24
+
25
+ CVE-2019-16782.
26
+
27
+
28
+ ## Rails 5.2.4 (November 27, 2019) ##
29
+
30
+ * No changes.
31
+
32
+
33
+ ## Rails 5.2.3 (March 27, 2019) ##
34
+
35
+ * Allow using `public` and `no-cache` together in the the Cache Control header.
36
+
37
+ Before this change, even if `public` was specified in the Cache Control header,
38
+ it was excluded when `no-cache` was included. This change preserves the
39
+ `public` value as is.
40
+
41
+ Fixes #34780.
42
+
43
+ *Yuji Yaginuma*
44
+
45
+ * Allow `nil` params for `ActionController::TestCase`.
46
+
47
+ *Ryo Nakamura*
48
+
49
+
50
+ ## Rails 5.2.2.1 (March 11, 2019) ##
51
+
52
+ * No changes.
53
+
54
+
1
55
  ## Rails 5.2.2 (December 04, 2018) ##
2
56
 
3
57
  * Reset Capybara sessions if failed system test screenshot raising an exception.
@@ -164,6 +218,34 @@
164
218
 
165
219
  * Matches behavior of `Hash#each` in `ActionController::Parameters#each`.
166
220
 
221
+ Rails 5.0 introduced a bug when looping through controller params using `each`. Only the keys of params hash were passed to the block, e.g.
222
+
223
+ # Parameters: {"param"=>"1", "param_two"=>"2"}
224
+ def index
225
+ params.each do |name|
226
+ puts name
227
+ end
228
+ end
229
+
230
+ # Prints
231
+ # param
232
+ # param_two
233
+
234
+ In Rails 5.2 the bug has been fixed and name will be an array (which was the behavior for all versions prior to 5.0), instead of a string.
235
+
236
+ To fix the code above simply change as per example below:
237
+
238
+ # Parameters: {"param"=>"1", "param_two"=>"2"}
239
+ def index
240
+ params.each do |name, value|
241
+ puts name
242
+ end
243
+ end
244
+
245
+ # Prints
246
+ # param
247
+ # param_two
248
+
167
249
  *Dominic Cleal*
168
250
 
169
251
  * Add `Referrer-Policy` header to default headers set.
@@ -26,10 +26,10 @@ module ActionController
26
26
  end
27
27
  end
28
28
 
29
- def build(action, app = Proc.new)
29
+ def build(action, app = nil, &block)
30
30
  action = action.to_s
31
31
 
32
- middlewares.reverse.inject(app) do |a, middleware|
32
+ middlewares.reverse.inject(app || block) do |a, middleware|
33
33
  middleware.valid?(action) ? middleware.build(a) : a
34
34
  end
35
35
  end
@@ -93,7 +93,7 @@ module ActionController
93
93
  end
94
94
 
95
95
  def model
96
- super || synchronize { super || self.model = _default_wrap_model }
96
+ super || self.model = _default_wrap_model
97
97
  end
98
98
 
99
99
  def include
@@ -115,7 +115,7 @@ module ActionController
115
115
 
116
116
  if m.respond_to?(:nested_attributes_options) && m.nested_attributes_options.keys.any?
117
117
  self.include += m.nested_attributes_options.keys.map do |key|
118
- key.to_s.concat("_attributes")
118
+ key.to_s.dup.concat("_attributes")
119
119
  end
120
120
  end
121
121
 
@@ -318,13 +318,15 @@ module ActionController #:nodoc:
318
318
  action_path = normalize_action_path(action)
319
319
  per_form_csrf_token(session, action_path, method)
320
320
  else
321
- real_csrf_token(session)
321
+ global_csrf_token(session)
322
322
  end
323
323
 
324
324
  one_time_pad = SecureRandom.random_bytes(AUTHENTICITY_TOKEN_LENGTH)
325
325
  encrypted_csrf_token = xor_byte_strings(one_time_pad, raw_token)
326
326
  masked_token = one_time_pad + encrypted_csrf_token
327
- Base64.strict_encode64(masked_token)
327
+ Base64.urlsafe_encode64(masked_token, padding: false)
328
+
329
+ mask_token(raw_token)
328
330
  end
329
331
 
330
332
  # Checks the client's masked token to see if it matches the
@@ -354,7 +356,8 @@ module ActionController #:nodoc:
354
356
  elsif masked_token.length == AUTHENTICITY_TOKEN_LENGTH * 2
355
357
  csrf_token = unmask_token(masked_token)
356
358
 
357
- compare_with_real_token(csrf_token, session) ||
359
+ compare_with_global_token(csrf_token, session) ||
360
+ compare_with_real_token(csrf_token, session) ||
358
361
  valid_per_form_csrf_token?(csrf_token, session)
359
362
  else
360
363
  false # Token is malformed.
@@ -369,10 +372,21 @@ module ActionController #:nodoc:
369
372
  xor_byte_strings(one_time_pad, encrypted_csrf_token)
370
373
  end
371
374
 
375
+ def mask_token(raw_token) # :doc:
376
+ one_time_pad = SecureRandom.random_bytes(AUTHENTICITY_TOKEN_LENGTH)
377
+ encrypted_csrf_token = xor_byte_strings(one_time_pad, raw_token)
378
+ masked_token = one_time_pad + encrypted_csrf_token
379
+ Base64.strict_encode64(masked_token)
380
+ end
381
+
372
382
  def compare_with_real_token(token, session) # :doc:
373
383
  ActiveSupport::SecurityUtils.fixed_length_secure_compare(token, real_csrf_token(session))
374
384
  end
375
385
 
386
+ def compare_with_global_token(token, session) # :doc:
387
+ ActiveSupport::SecurityUtils.fixed_length_secure_compare(token, global_csrf_token(session))
388
+ end
389
+
376
390
  def valid_per_form_csrf_token?(token, session) # :doc:
377
391
  if per_form_csrf_tokens
378
392
  correct_token = per_form_csrf_token(
@@ -393,10 +407,21 @@ module ActionController #:nodoc:
393
407
  end
394
408
 
395
409
  def per_form_csrf_token(session, action_path, method) # :doc:
410
+ csrf_token_hmac(session, [action_path, method.downcase].join("#"))
411
+ end
412
+
413
+ GLOBAL_CSRF_TOKEN_IDENTIFIER = "!real_csrf_token"
414
+ private_constant :GLOBAL_CSRF_TOKEN_IDENTIFIER
415
+
416
+ def global_csrf_token(session) # :doc:
417
+ csrf_token_hmac(session, GLOBAL_CSRF_TOKEN_IDENTIFIER)
418
+ end
419
+
420
+ def csrf_token_hmac(session, identifier) # :doc:
396
421
  OpenSSL::HMAC.digest(
397
422
  OpenSSL::Digest::SHA256.new,
398
423
  real_csrf_token(session),
399
- [action_path, method.downcase].join("#")
424
+ identifier
400
425
  )
401
426
  end
402
427
 
@@ -337,6 +337,8 @@ module ActionController
337
337
  @parameters.each_pair do |key, value|
338
338
  yield [key, convert_hashes_to_parameters(key, value)]
339
339
  end
340
+
341
+ self
340
342
  end
341
343
  alias_method :each, :each_pair
342
344
 
@@ -457,9 +457,10 @@ module ActionController
457
457
  # respectively which will make tests more expressive.
458
458
  #
459
459
  # Note that the request method is not verified.
460
- def process(action, method: "GET", params: {}, session: nil, body: nil, flash: {}, format: nil, xhr: false, as: nil)
460
+ def process(action, method: "GET", params: nil, session: nil, body: nil, flash: {}, format: nil, xhr: false, as: nil)
461
461
  check_required_ivars
462
462
 
463
+ action = action.to_s.dup
463
464
  http_method = method.to_s.upcase
464
465
 
465
466
  @html_document = nil
@@ -485,17 +486,17 @@ module ActionController
485
486
  format ||= as
486
487
  end
487
488
 
488
- parameters = params.symbolize_keys
489
+ parameters = (params || {}).symbolize_keys
489
490
 
490
491
  if format
491
492
  parameters[:format] = format
492
493
  end
493
494
 
494
- generated_extras = @routes.generate_extras(parameters.merge(controller: controller_class_name, action: action.to_s))
495
+ generated_extras = @routes.generate_extras(parameters.merge(controller: controller_class_name, action: action))
495
496
  generated_path = generated_path(generated_extras)
496
497
  query_string_keys = query_parameter_names(generated_extras)
497
498
 
498
- @request.assign_parameters(@routes, controller_class_name, action.to_s, parameters, generated_path, query_string_keys)
499
+ @request.assign_parameters(@routes, controller_class_name, action, parameters, generated_path, query_string_keys)
499
500
 
500
501
  @request.session.update(session) if session
501
502
  @request.flash.update(flash || {})
@@ -83,10 +83,11 @@ module ActionDispatch
83
83
  end
84
84
 
85
85
  module Session
86
- autoload :AbstractStore, "action_dispatch/middleware/session/abstract_store"
87
- autoload :CookieStore, "action_dispatch/middleware/session/cookie_store"
88
- autoload :MemCacheStore, "action_dispatch/middleware/session/mem_cache_store"
89
- autoload :CacheStore, "action_dispatch/middleware/session/cache_store"
86
+ autoload :AbstractStore, "action_dispatch/middleware/session/abstract_store"
87
+ autoload :AbstractSecureStore, "action_dispatch/middleware/session/abstract_store"
88
+ autoload :CookieStore, "action_dispatch/middleware/session/cookie_store"
89
+ autoload :MemCacheStore, "action_dispatch/middleware/session/mem_cache_store"
90
+ autoload :CacheStore, "action_dispatch/middleware/session/cache_store"
90
91
  end
91
92
 
92
93
  mattr_accessor :test_app
@@ -197,10 +197,12 @@ module ActionDispatch
197
197
  if control.empty?
198
198
  # Let middleware handle default behavior
199
199
  elsif control[:no_cache]
200
- self._cache_control = NO_CACHE
201
- if control[:extras]
202
- self._cache_control = _cache_control + ", #{control[:extras].join(', ')}"
203
- end
200
+ options = []
201
+ options << PUBLIC if control[:public]
202
+ options << NO_CACHE
203
+ options.concat(control[:extras]) if control[:extras]
204
+
205
+ self._cache_control = options.join(", ")
204
206
  else
205
207
  extras = control[:extras]
206
208
  max_age = control[:max_age]
@@ -74,6 +74,11 @@ module ActionDispatch
74
74
  else
75
75
  [Mime[:html]]
76
76
  end
77
+
78
+ v = v.select do |format|
79
+ format.symbol || format.ref == "*/*"
80
+ end
81
+
77
82
  set_header k, v
78
83
  end
79
84
  end
@@ -119,7 +119,8 @@ module ActionDispatch
119
119
 
120
120
  class UnanchoredRegexp < AnchoredRegexp # :nodoc:
121
121
  def accept(node)
122
- %r{\A#{visit node}}
122
+ path = visit node
123
+ path == "/" ? %r{\A/} : %r{\A#{path}(?:\b|\Z|/)}
123
124
  end
124
125
  end
125
126
 
@@ -83,7 +83,21 @@ module ActionDispatch
83
83
  include SessionObject
84
84
 
85
85
  private
86
+ def set_cookie(request, session_id, cookie)
87
+ request.cookie_jar[key] = cookie
88
+ end
89
+ end
90
+
91
+ class AbstractSecureStore < Rack::Session::Abstract::PersistedSecure
92
+ include Compatibility
93
+ include StaleSessionCheck
94
+ include SessionObject
95
+
96
+ def generate_sid
97
+ Rack::Session::SessionId.new(super)
98
+ end
86
99
 
100
+ private
87
101
  def set_cookie(request, session_id, cookie)
88
102
  request.cookie_jar[key] = cookie
89
103
  end
@@ -12,7 +12,7 @@ module ActionDispatch
12
12
  # * <tt>cache</tt> - The cache to use. If it is not specified, <tt>Rails.cache</tt> will be used.
13
13
  # * <tt>expire_after</tt> - The length of time a session will be stored before automatically expiring.
14
14
  # By default, the <tt>:expires_in</tt> option of the cache is used.
15
- class CacheStore < AbstractStore
15
+ class CacheStore < AbstractSecureStore
16
16
  def initialize(app, options = {})
17
17
  @cache = options[:cache] || Rails.cache
18
18
  options[:expire_after] ||= @cache.options[:expires_in]
@@ -21,7 +21,7 @@ module ActionDispatch
21
21
 
22
22
  # Get a session from the cache.
23
23
  def find_session(env, sid)
24
- unless sid && (session = @cache.read(cache_key(sid)))
24
+ unless sid && (session = get_session_with_fallback(sid))
25
25
  sid, session = generate_sid, {}
26
26
  end
27
27
  [sid, session]
@@ -29,7 +29,7 @@ module ActionDispatch
29
29
 
30
30
  # Set a session in the cache.
31
31
  def write_session(env, sid, session, options)
32
- key = cache_key(sid)
32
+ key = cache_key(sid.private_id)
33
33
  if session
34
34
  @cache.write(key, session, expires_in: options[:expire_after])
35
35
  else
@@ -40,14 +40,19 @@ module ActionDispatch
40
40
 
41
41
  # Remove a session from the cache.
42
42
  def delete_session(env, sid, options)
43
- @cache.delete(cache_key(sid))
43
+ @cache.delete(cache_key(sid.private_id))
44
+ @cache.delete(cache_key(sid.public_id))
44
45
  generate_sid
45
46
  end
46
47
 
47
48
  private
48
49
  # Turn the session id into a cache key.
49
- def cache_key(sid)
50
- "_session_id:#{sid}"
50
+ def cache_key(id)
51
+ "_session_id:#{id}"
52
+ end
53
+
54
+ def get_session_with_fallback(sid)
55
+ @cache.read(cache_key(sid.private_id)) || @cache.read(cache_key(sid.public_id))
51
56
  end
52
57
  end
53
58
  end
@@ -29,9 +29,10 @@ module ActionDispatch
29
29
  #
30
30
  # Rails.application.config.session_store :cookie_store, key: '_your_app_session'
31
31
  #
32
- # By default, your secret key base is derived from your application name in
33
- # the test and development environments. In all other environments, it is stored
34
- # encrypted in the <tt>config/credentials.yml.enc</tt> file.
32
+ # In the development and test environments your application's secret key base is
33
+ # generated by Rails and stored in a temporary file in <tt>tmp/development_secret.txt</tt>.
34
+ # In all other environments, it is stored encrypted in the
35
+ # <tt>config/credentials.yml.enc</tt> file.
35
36
  #
36
37
  # If your application was not updated to Rails 5.2 defaults, the secret_key_base
37
38
  # will be found in the old <tt>config/secrets.yml</tt> file.
@@ -50,7 +51,16 @@ module ActionDispatch
50
51
  # would set the session cookie to expire automatically 14 days after creation.
51
52
  # Other useful options include <tt>:key</tt>, <tt>:secure</tt> and
52
53
  # <tt>:httponly</tt>.
53
- class CookieStore < AbstractStore
54
+ class CookieStore < AbstractSecureStore
55
+ class SessionId < DelegateClass(Rack::Session::SessionId)
56
+ attr_reader :cookie_value
57
+
58
+ def initialize(session_id, cookie_value = {})
59
+ super(session_id)
60
+ @cookie_value = cookie_value
61
+ end
62
+ end
63
+
54
64
  def initialize(app, options = {})
55
65
  super(app, options.merge!(cookie_only: true))
56
66
  end
@@ -58,7 +68,7 @@ module ActionDispatch
58
68
  def delete_session(req, session_id, options)
59
69
  new_sid = generate_sid unless options[:drop]
60
70
  # Reset hash and Assign the new session id
61
- req.set_header("action_dispatch.request.unsigned_session_cookie", new_sid ? { "session_id" => new_sid } : {})
71
+ req.set_header("action_dispatch.request.unsigned_session_cookie", new_sid ? { "session_id" => new_sid.public_id } : {})
62
72
  new_sid
63
73
  end
64
74
 
@@ -66,7 +76,7 @@ module ActionDispatch
66
76
  stale_session_check! do
67
77
  data = unpacked_cookie_data(req)
68
78
  data = persistent_session_id!(data)
69
- [data["session_id"], data]
79
+ [Rack::Session::SessionId.new(data["session_id"]), data]
70
80
  end
71
81
  end
72
82
 
@@ -74,7 +84,8 @@ module ActionDispatch
74
84
 
75
85
  def extract_session_id(req)
76
86
  stale_session_check! do
77
- unpacked_cookie_data(req)["session_id"]
87
+ sid = unpacked_cookie_data(req)["session_id"]
88
+ sid && Rack::Session::SessionId.new(sid)
78
89
  end
79
90
  end
80
91
 
@@ -92,13 +103,13 @@ module ActionDispatch
92
103
 
93
104
  def persistent_session_id!(data, sid = nil)
94
105
  data ||= {}
95
- data["session_id"] ||= sid || generate_sid
106
+ data["session_id"] ||= sid || generate_sid.public_id
96
107
  data
97
108
  end
98
109
 
99
110
  def write_session(req, sid, session_data, options)
100
- session_data["session_id"] = sid
101
- session_data
111
+ session_data["session_id"] = sid.public_id
112
+ SessionId.new(sid, session_data)
102
113
  end
103
114
 
104
115
  def set_cookie(request, session_id, cookie)
@@ -97,8 +97,8 @@ module ActionDispatch
97
97
  middlewares.push(build_middleware(klass, args, block))
98
98
  end
99
99
 
100
- def build(app = Proc.new)
101
- middlewares.freeze.reverse.inject(app) { |a, e| e.build(a) }
100
+ def build(app = nil, &block)
101
+ middlewares.freeze.reverse.inject(app || block) { |a, e| e.build(a) }
102
102
  end
103
103
 
104
104
  private
@@ -90,7 +90,13 @@ module ActionDispatch
90
90
  # +nil+ if the given key is not found in the session.
91
91
  def [](key)
92
92
  load_for_read!
93
- @delegate[key.to_s]
93
+ key = key.to_s
94
+
95
+ if key == "session_id"
96
+ id&.public_id
97
+ else
98
+ @delegate[key]
99
+ end
94
100
  end
95
101
 
96
102
  # Returns true if the session has the given key or false.
@@ -9,8 +9,8 @@ module ActionPack
9
9
  module VERSION
10
10
  MAJOR = 5
11
11
  MINOR = 2
12
- TINY = 2
13
- PRE = nil
12
+ TINY = 4
13
+ PRE = "5"
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: actionpack
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.2.2
4
+ version: 5.2.4.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-12-04 00:00:00.000000000 Z
11
+ date: 2021-02-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 5.2.2
19
+ version: 5.2.4.5
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 5.2.2
26
+ version: 5.2.4.5
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rack
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -31,6 +31,9 @@ dependencies:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '2.0'
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 2.0.8
34
37
  type: :runtime
35
38
  prerelease: false
36
39
  version_requirements: !ruby/object:Gem::Requirement
@@ -38,6 +41,9 @@ dependencies:
38
41
  - - "~>"
39
42
  - !ruby/object:Gem::Version
40
43
  version: '2.0'
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 2.0.8
41
47
  - !ruby/object:Gem::Dependency
42
48
  name: rack-test
43
49
  requirement: !ruby/object:Gem::Requirement
@@ -92,28 +98,28 @@ dependencies:
92
98
  requirements:
93
99
  - - '='
94
100
  - !ruby/object:Gem::Version
95
- version: 5.2.2
101
+ version: 5.2.4.5
96
102
  type: :runtime
97
103
  prerelease: false
98
104
  version_requirements: !ruby/object:Gem::Requirement
99
105
  requirements:
100
106
  - - '='
101
107
  - !ruby/object:Gem::Version
102
- version: 5.2.2
108
+ version: 5.2.4.5
103
109
  - !ruby/object:Gem::Dependency
104
110
  name: activemodel
105
111
  requirement: !ruby/object:Gem::Requirement
106
112
  requirements:
107
113
  - - '='
108
114
  - !ruby/object:Gem::Version
109
- version: 5.2.2
115
+ version: 5.2.4.5
110
116
  type: :development
111
117
  prerelease: false
112
118
  version_requirements: !ruby/object:Gem::Requirement
113
119
  requirements:
114
120
  - - '='
115
121
  - !ruby/object:Gem::Version
116
- version: 5.2.2
122
+ version: 5.2.4.5
117
123
  description: Web apps on Rails. Simple, battle-tested conventions for building and
118
124
  testing MVC web applications. Works with any Rack-compatible server.
119
125
  email: david@loudthinking.com
@@ -293,8 +299,8 @@ homepage: http://rubyonrails.org
293
299
  licenses:
294
300
  - MIT
295
301
  metadata:
296
- source_code_uri: https://github.com/rails/rails/tree/v5.2.2/actionpack
297
- changelog_uri: https://github.com/rails/rails/blob/v5.2.2/actionpack/CHANGELOG.md
302
+ source_code_uri: https://github.com/rails/rails/tree/v5.2.4.5/actionpack
303
+ changelog_uri: https://github.com/rails/rails/blob/v5.2.4.5/actionpack/CHANGELOG.md
298
304
  post_install_message:
299
305
  rdoc_options: []
300
306
  require_paths:
@@ -311,8 +317,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
311
317
  version: '0'
312
318
  requirements:
313
319
  - none
314
- rubyforge_project:
315
- rubygems_version: 2.7.6
320
+ rubygems_version: 3.0.3
316
321
  signing_key:
317
322
  specification_version: 4
318
323
  summary: Web-flow and rendering framework putting the VC in MVC (part of Rails).