actionpack 7.0.3.1 → 7.0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +28 -0
- data/lib/abstract_controller/helpers.rb +1 -1
- data/lib/action_controller/metal/redirecting.rb +7 -2
- data/lib/action_controller/metal/rendering.rb +2 -2
- data/lib/action_controller/metal/strong_parameters.rb +7 -2
- data/lib/action_dispatch/http/cache.rb +1 -1
- data/lib/action_dispatch/http/response.rb +2 -3
- data/lib/action_dispatch/middleware/cookies.rb +30 -23
- data/lib/action_dispatch/middleware/server_timing.rb +53 -10
- data/lib/action_dispatch/middleware/session/cookie_store.rb +7 -7
- data/lib/action_dispatch/routing/mapper.rb +1 -1
- data/lib/action_dispatch/testing/test_response.rb +20 -2
- data/lib/action_pack/gem_version.rb +1 -1
- metadata +12 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5f31d845cb672a69a48bf5a99d24da4cc0a1911dd90592b7f569954a08040d32
|
4
|
+
data.tar.gz: 4f82a27ee5dba8c642621ab247ef345b7daff0e9e4fe25c3ba81163a2a31b8d5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7094329330497de30fa9dbae232a2563a3699129681dbba34092db10f3e07d97b9905abe2d4339f50c39b8f45c6e9765a77523c379dbe53f3ff96cb544586483
|
7
|
+
data.tar.gz: db8c045d237562750468b511cd54990c2fe0069fe7942e663f013f6cdfa30e7211b8f9874cdc7187dc0b16f1238cb331dde86bbd38f796688935e541b0fcac25
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,31 @@
|
|
1
|
+
## Rails 7.0.4.1 (January 17, 2023) ##
|
2
|
+
|
3
|
+
* Fix sec issue with _url_host_allowed?
|
4
|
+
|
5
|
+
Disallow certain strings from `_url_host_allowed?` to avoid a redirect
|
6
|
+
to malicious sites.
|
7
|
+
|
8
|
+
[CVE-2023-22797]
|
9
|
+
|
10
|
+
* Avoid regex backtracking on If-None-Match header
|
11
|
+
|
12
|
+
[CVE-2023-22795]
|
13
|
+
|
14
|
+
* Use string#split instead of regex for domain parts
|
15
|
+
|
16
|
+
[CVE-2023-22792]
|
17
|
+
|
18
|
+
|
19
|
+
## Rails 7.0.4 (September 09, 2022) ##
|
20
|
+
|
21
|
+
* Prevent `ActionDispatch::ServerTiming` from overwriting existing values in `Server-Timing`.
|
22
|
+
|
23
|
+
Previously, if another middleware down the chain set `Server-Timing` header,
|
24
|
+
it would overwritten by `ActionDispatch::ServerTiming`.
|
25
|
+
|
26
|
+
*Jakub Malinowski*
|
27
|
+
|
28
|
+
|
1
29
|
## Rails 7.0.3.1 (July 12, 2022) ##
|
2
30
|
|
3
31
|
* No changes.
|
@@ -110,7 +110,7 @@ module AbstractController
|
|
110
110
|
# The last two assume that <tt>"foo".camelize</tt> returns "Foo".
|
111
111
|
#
|
112
112
|
# When strings or symbols are passed, the method finds the actual module
|
113
|
-
# object using
|
113
|
+
# object using String#constantize. Therefore, if the module has not been
|
114
114
|
# yet loaded, it has to be autoloadable, which is normally the case.
|
115
115
|
#
|
116
116
|
# Namespaces are supported. The following calls include +Foo::BarHelper+:
|
@@ -117,7 +117,7 @@ module ActionController
|
|
117
117
|
# * <tt>:allow_other_host</tt> - Allow or disallow redirection to the host that is different to the current host, defaults to true.
|
118
118
|
#
|
119
119
|
# All other options that can be passed to #redirect_to are accepted as
|
120
|
-
# options and the behavior is identical.
|
120
|
+
# options, and the behavior is identical.
|
121
121
|
def redirect_back_or_to(fallback_location, allow_other_host: _allow_other_host, **options)
|
122
122
|
if request.referer && (allow_other_host || _url_host_allowed?(request.referer))
|
123
123
|
redirect_to request.referer, allow_other_host: allow_other_host, **options
|
@@ -195,7 +195,12 @@ module ActionController
|
|
195
195
|
end
|
196
196
|
|
197
197
|
def _url_host_allowed?(url)
|
198
|
-
|
198
|
+
host = URI(url.to_s).host
|
199
|
+
|
200
|
+
return true if host == request.host
|
201
|
+
return false unless host.nil?
|
202
|
+
return false unless url.to_s.start_with?("/")
|
203
|
+
return !url.to_s.start_with?("//")
|
199
204
|
rescue ArgumentError, URI::Error
|
200
205
|
false
|
201
206
|
end
|
@@ -78,8 +78,8 @@ module ActionController
|
|
78
78
|
end
|
79
79
|
|
80
80
|
def _set_vary_header
|
81
|
-
if
|
82
|
-
|
81
|
+
if response.headers["Vary"].blank? && request.should_apply_vary_header?
|
82
|
+
response.headers["Vary"] = "Accept"
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
@@ -279,10 +279,15 @@ module ActionController
|
|
279
279
|
@parameters == other
|
280
280
|
end
|
281
281
|
end
|
282
|
-
|
282
|
+
|
283
|
+
def eql?(other)
|
284
|
+
self.class == other.class &&
|
285
|
+
permitted? == other.permitted? &&
|
286
|
+
parameters.eql?(other.parameters)
|
287
|
+
end
|
283
288
|
|
284
289
|
def hash
|
285
|
-
[@parameters
|
290
|
+
[self.class, @parameters, @permitted].hash
|
286
291
|
end
|
287
292
|
|
288
293
|
# Returns a safe <tt>ActiveSupport::HashWithIndifferentAccess</tt>
|
@@ -21,9 +21,8 @@ module ActionDispatch # :nodoc:
|
|
21
21
|
# Nevertheless, integration tests may want to inspect controller responses in
|
22
22
|
# more detail, and that's when \Response can be useful for application
|
23
23
|
# developers. Integration test methods such as
|
24
|
-
#
|
25
|
-
#
|
26
|
-
# TestResponse (which are of course also of type \Response).
|
24
|
+
# Integration::RequestHelpers#get and Integration::RequestHelpers#post return
|
25
|
+
# objects of type TestResponse (which are of course also of type \Response).
|
27
26
|
#
|
28
27
|
# For example, the following demo integration test prints the body of the
|
29
28
|
# controller response to the console:
|
@@ -92,7 +92,7 @@ module ActionDispatch
|
|
92
92
|
include RequestCookieMethods
|
93
93
|
end
|
94
94
|
|
95
|
-
# Read and write data to cookies through ActionController#cookies.
|
95
|
+
# Read and write data to cookies through ActionController::Base#cookies.
|
96
96
|
#
|
97
97
|
# When reading cookie data, the data is read from the HTTP request header, Cookie.
|
98
98
|
# When writing cookie data, the data is sent out in the HTTP response header, Set-Cookie.
|
@@ -178,8 +178,7 @@ module ActionDispatch
|
|
178
178
|
# only HTTP. Defaults to +false+.
|
179
179
|
# * <tt>:same_site</tt> - The value of the +SameSite+ cookie attribute, which
|
180
180
|
# determines how this cookie should be restricted in cross-site contexts.
|
181
|
-
# Possible values are
|
182
|
-
# +:lax+.
|
181
|
+
# Possible values are +:none+, +:lax+, and +:strict+. Defaults to +:lax+.
|
183
182
|
class Cookies
|
184
183
|
HTTP_HEADER = "Set-Cookie"
|
185
184
|
GENERATOR_KEY = "action_dispatch.key_generator"
|
@@ -291,20 +290,6 @@ module ActionDispatch
|
|
291
290
|
class CookieJar # :nodoc:
|
292
291
|
include Enumerable, ChainedCookieJars
|
293
292
|
|
294
|
-
# This regular expression is used to split the levels of a domain.
|
295
|
-
# The top level domain can be any string without a period or
|
296
|
-
# **.**, ***.** style TLDs like co.uk or com.au
|
297
|
-
#
|
298
|
-
# www.example.co.uk gives:
|
299
|
-
# $& => example.co.uk
|
300
|
-
#
|
301
|
-
# example.com gives:
|
302
|
-
# $& => example.com
|
303
|
-
#
|
304
|
-
# lots.of.subdomains.example.local gives:
|
305
|
-
# $& => example.local
|
306
|
-
DOMAIN_REGEXP = /[^.]*\.([^.]*|..\...|...\...)$/
|
307
|
-
|
308
293
|
def self.build(req, cookies)
|
309
294
|
jar = new(req)
|
310
295
|
jar.update(cookies)
|
@@ -457,13 +442,35 @@ module ActionDispatch
|
|
457
442
|
options[:same_site] ||= cookies_same_site_protection.call(request)
|
458
443
|
|
459
444
|
if options[:domain] == :all || options[:domain] == "all"
|
460
|
-
|
461
|
-
|
445
|
+
cookie_domain = ""
|
446
|
+
dot_splitted_host = request.host.split('.', -1)
|
447
|
+
|
448
|
+
# Case where request.host is not an IP address or it's an invalid domain
|
449
|
+
# (ip confirms to the domain structure we expect so we explicitly check for ip)
|
450
|
+
if request.host.match?(/^[\d.]+$/) || dot_splitted_host.include?("") || dot_splitted_host.length == 1
|
451
|
+
options[:domain] = nil
|
452
|
+
return
|
453
|
+
end
|
454
|
+
|
455
|
+
# If there is a provided tld length then we use it otherwise default domain.
|
456
|
+
if options[:tld_length].present?
|
457
|
+
# Case where the tld_length provided is valid
|
458
|
+
if dot_splitted_host.length >= options[:tld_length]
|
459
|
+
cookie_domain = dot_splitted_host.last(options[:tld_length]).join('.')
|
460
|
+
end
|
461
|
+
# Case where tld_length is not provided
|
462
|
+
else
|
463
|
+
# Regular TLDs
|
464
|
+
if !(/([^.]{2,3}\.[^.]{2})$/.match?(request.host))
|
465
|
+
cookie_domain = dot_splitted_host.last(2).join('.')
|
466
|
+
# **.**, ***.** style TLDs like co.uk and com.au
|
467
|
+
else
|
468
|
+
cookie_domain = dot_splitted_host.last(3).join('.')
|
469
|
+
end
|
470
|
+
end
|
462
471
|
|
463
|
-
|
464
|
-
|
465
|
-
options[:domain] = if !request.host.match?(/^[\d.]+$/) && (request.host =~ domain_regexp)
|
466
|
-
".#{$&}"
|
472
|
+
options[:domain] = if cookie_domain.present?
|
473
|
+
".#{cookie_domain}"
|
467
474
|
end
|
468
475
|
elsif options[:domain].is_a? Array
|
469
476
|
# If host matches one of the supplied domains.
|
@@ -6,28 +6,71 @@ module ActionDispatch
|
|
6
6
|
class ServerTiming
|
7
7
|
SERVER_TIMING_HEADER = "Server-Timing"
|
8
8
|
|
9
|
+
class Subscriber # :nodoc:
|
10
|
+
include Singleton
|
11
|
+
KEY = :action_dispatch_server_timing_events
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@mutex = Mutex.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def call(event)
|
18
|
+
if events = ActiveSupport::IsolatedExecutionState[KEY]
|
19
|
+
events << event
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def collect_events
|
24
|
+
events = []
|
25
|
+
ActiveSupport::IsolatedExecutionState[KEY] = events
|
26
|
+
yield
|
27
|
+
events
|
28
|
+
ensure
|
29
|
+
ActiveSupport::IsolatedExecutionState.delete(KEY)
|
30
|
+
end
|
31
|
+
|
32
|
+
def ensure_subscribed
|
33
|
+
@mutex.synchronize do
|
34
|
+
# Subscribe to all events, except those beginning with "!"
|
35
|
+
# Ideally we would be more selective of what is being measured
|
36
|
+
@subscriber ||= ActiveSupport::Notifications.subscribe(/\A[^!]/, self)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def unsubscribe
|
41
|
+
@mutex.synchronize do
|
42
|
+
ActiveSupport::Notifications.unsubscribe @subscriber
|
43
|
+
@subscriber = nil
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.unsubscribe # :nodoc:
|
49
|
+
Subscriber.instance.unsubscribe
|
50
|
+
end
|
51
|
+
|
9
52
|
def initialize(app)
|
10
53
|
@app = app
|
54
|
+
@subscriber = Subscriber.instance
|
55
|
+
@subscriber.ensure_subscribed
|
11
56
|
end
|
12
57
|
|
13
58
|
def call(env)
|
14
|
-
|
15
|
-
|
16
|
-
|
59
|
+
response = nil
|
60
|
+
events = @subscriber.collect_events do
|
61
|
+
response = @app.call(env)
|
17
62
|
end
|
18
63
|
|
19
|
-
|
20
|
-
@app.call(env)
|
21
|
-
ensure
|
22
|
-
ActiveSupport::Notifications.unsubscribe(subscriber)
|
23
|
-
end
|
64
|
+
headers = response[1]
|
24
65
|
|
25
66
|
header_info = events.group_by(&:name).map do |event_name, events_collection|
|
26
|
-
"
|
67
|
+
"%s;dur=%.2f" % [event_name, events_collection.sum(&:duration)]
|
27
68
|
end
|
69
|
+
|
70
|
+
header_info.prepend(headers[SERVER_TIMING_HEADER]) if headers[SERVER_TIMING_HEADER].present?
|
28
71
|
headers[SERVER_TIMING_HEADER] = header_info.join(", ")
|
29
72
|
|
30
|
-
|
73
|
+
response
|
31
74
|
end
|
32
75
|
end
|
33
76
|
end
|
@@ -9,14 +9,14 @@ module ActionDispatch
|
|
9
9
|
# This cookie-based session store is the Rails default. It is
|
10
10
|
# dramatically faster than the alternatives.
|
11
11
|
#
|
12
|
-
# Sessions typically contain at most a
|
13
|
-
# within the 4096 bytes cookie size limit. A CookieOverflow exception is raised if
|
12
|
+
# Sessions typically contain at most a user ID and flash message; both fit
|
13
|
+
# within the 4096 bytes cookie size limit. A +CookieOverflow+ exception is raised if
|
14
14
|
# you attempt to store more than 4096 bytes of data.
|
15
15
|
#
|
16
16
|
# The cookie jar used for storage is automatically configured to be the
|
17
17
|
# best possible option given your application's configuration.
|
18
18
|
#
|
19
|
-
# Your cookies will be encrypted using your
|
19
|
+
# Your cookies will be encrypted using your application's +secret_key_base+. This
|
20
20
|
# goes a step further than signed cookies in that encrypted cookies cannot
|
21
21
|
# be altered or read by users. This is the default starting in Rails 4.
|
22
22
|
#
|
@@ -24,20 +24,20 @@ module ActionDispatch
|
|
24
24
|
#
|
25
25
|
# Rails.application.config.session_store :cookie_store, key: '_your_app_session'
|
26
26
|
#
|
27
|
-
# In the development and test environments your application's
|
27
|
+
# In the development and test environments your application's +secret_key_base+ is
|
28
28
|
# generated by Rails and stored in a temporary file in <tt>tmp/development_secret.txt</tt>.
|
29
29
|
# In all other environments, it is stored encrypted in the
|
30
30
|
# <tt>config/credentials.yml.enc</tt> file.
|
31
31
|
#
|
32
|
-
# If your application was not updated to Rails 5.2 defaults, the secret_key_base
|
32
|
+
# If your application was not updated to Rails 5.2 defaults, the +secret_key_base+
|
33
33
|
# will be found in the old <tt>config/secrets.yml</tt> file.
|
34
34
|
#
|
35
|
-
# Note that changing your secret_key_base will invalidate all existing session.
|
35
|
+
# Note that changing your +secret_key_base+ will invalidate all existing session.
|
36
36
|
# Additionally, you should take care to make sure you are not relying on the
|
37
37
|
# ability to decode signed cookies generated by your app in external
|
38
38
|
# applications or JavaScript before changing it.
|
39
39
|
#
|
40
|
-
# Because CookieStore extends Rack::Session::Abstract::Persisted
|
40
|
+
# Because CookieStore extends +Rack::Session::Abstract::Persisted+, many of the
|
41
41
|
# options described there can be used to customize the session cookie that
|
42
42
|
# is generated. For example:
|
43
43
|
#
|
@@ -609,7 +609,7 @@ module ActionDispatch
|
|
609
609
|
target_as = name_for_action(options[:as], path)
|
610
610
|
options[:via] ||= :all
|
611
611
|
|
612
|
-
match(path,
|
612
|
+
match(path, { to: app, anchor: false, format: false }.merge(options))
|
613
613
|
|
614
614
|
define_generate_prefix(app, target_as) if rails_app
|
615
615
|
self
|
@@ -3,8 +3,8 @@
|
|
3
3
|
require "action_dispatch/testing/request_encoder"
|
4
4
|
|
5
5
|
module ActionDispatch
|
6
|
-
# Integration test methods such as
|
7
|
-
# and
|
6
|
+
# Integration test methods such as Integration::RequestHelpers#get
|
7
|
+
# and Integration::RequestHelpers#post return objects of class
|
8
8
|
# TestResponse, which represent the HTTP response results of the requested
|
9
9
|
# controller actions.
|
10
10
|
#
|
@@ -14,6 +14,24 @@ module ActionDispatch
|
|
14
14
|
new response.status, response.headers, response.body
|
15
15
|
end
|
16
16
|
|
17
|
+
# Returns a parsed body depending on the response MIME type. When a parser
|
18
|
+
# corresponding to the MIME type is not found, it returns the raw body.
|
19
|
+
#
|
20
|
+
# ==== Examples
|
21
|
+
# get "/posts"
|
22
|
+
# response.content_type # => "text/html; charset=utf-8"
|
23
|
+
# response.parsed_body.class # => String
|
24
|
+
# response.parsed_body # => "<!DOCTYPE html>\n<html>\n..."
|
25
|
+
#
|
26
|
+
# get "/posts.json"
|
27
|
+
# response.content_type # => "application/json; charset=utf-8"
|
28
|
+
# response.parsed_body.class # => Array
|
29
|
+
# response.parsed_body # => [{"id"=>42, "title"=>"Title"},...
|
30
|
+
#
|
31
|
+
# get "/posts/42.json"
|
32
|
+
# response.content_type # => "application/json; charset=utf-8"
|
33
|
+
# response.parsed_body.class # => Hash
|
34
|
+
# response.parsed_body # => {"id"=>42, "title"=>"Title"}
|
17
35
|
def parsed_body
|
18
36
|
@parsed_body ||= response_parser.call(body)
|
19
37
|
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: 7.0.
|
4
|
+
version: 7.0.4.1
|
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:
|
11
|
+
date: 2023-01-17 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: 7.0.
|
19
|
+
version: 7.0.4.1
|
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: 7.0.
|
26
|
+
version: 7.0.4.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rack
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -98,28 +98,28 @@ dependencies:
|
|
98
98
|
requirements:
|
99
99
|
- - '='
|
100
100
|
- !ruby/object:Gem::Version
|
101
|
-
version: 7.0.
|
101
|
+
version: 7.0.4.1
|
102
102
|
type: :runtime
|
103
103
|
prerelease: false
|
104
104
|
version_requirements: !ruby/object:Gem::Requirement
|
105
105
|
requirements:
|
106
106
|
- - '='
|
107
107
|
- !ruby/object:Gem::Version
|
108
|
-
version: 7.0.
|
108
|
+
version: 7.0.4.1
|
109
109
|
- !ruby/object:Gem::Dependency
|
110
110
|
name: activemodel
|
111
111
|
requirement: !ruby/object:Gem::Requirement
|
112
112
|
requirements:
|
113
113
|
- - '='
|
114
114
|
- !ruby/object:Gem::Version
|
115
|
-
version: 7.0.
|
115
|
+
version: 7.0.4.1
|
116
116
|
type: :development
|
117
117
|
prerelease: false
|
118
118
|
version_requirements: !ruby/object:Gem::Requirement
|
119
119
|
requirements:
|
120
120
|
- - '='
|
121
121
|
- !ruby/object:Gem::Version
|
122
|
-
version: 7.0.
|
122
|
+
version: 7.0.4.1
|
123
123
|
description: Web apps on Rails. Simple, battle-tested conventions for building and
|
124
124
|
testing MVC web applications. Works with any Rack-compatible server.
|
125
125
|
email: david@loudthinking.com
|
@@ -310,10 +310,10 @@ licenses:
|
|
310
310
|
- MIT
|
311
311
|
metadata:
|
312
312
|
bug_tracker_uri: https://github.com/rails/rails/issues
|
313
|
-
changelog_uri: https://github.com/rails/rails/blob/v7.0.
|
314
|
-
documentation_uri: https://api.rubyonrails.org/v7.0.
|
313
|
+
changelog_uri: https://github.com/rails/rails/blob/v7.0.4.1/actionpack/CHANGELOG.md
|
314
|
+
documentation_uri: https://api.rubyonrails.org/v7.0.4.1/
|
315
315
|
mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
|
316
|
-
source_code_uri: https://github.com/rails/rails/tree/v7.0.
|
316
|
+
source_code_uri: https://github.com/rails/rails/tree/v7.0.4.1/actionpack
|
317
317
|
rubygems_mfa_required: 'true'
|
318
318
|
post_install_message:
|
319
319
|
rdoc_options: []
|
@@ -331,7 +331,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
331
331
|
version: '0'
|
332
332
|
requirements:
|
333
333
|
- none
|
334
|
-
rubygems_version: 3.
|
334
|
+
rubygems_version: 3.4.3
|
335
335
|
signing_key:
|
336
336
|
specification_version: 4
|
337
337
|
summary: Web-flow and rendering framework putting the VC in MVC (part of Rails).
|