rack 2.2.3.1 → 2.2.6.4
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rack might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +36 -0
- data/README.rdoc +17 -3
- data/lib/rack/etag.rb +2 -0
- data/lib/rack/lint.rb +2 -2
- data/lib/rack/method_override.rb +1 -1
- data/lib/rack/multipart/parser.rb +15 -4
- data/lib/rack/multipart.rb +2 -2
- data/lib/rack/query_parser.rb +6 -2
- data/lib/rack/request.rb +2 -2
- data/lib/rack/urlmap.rb +1 -1
- data/lib/rack/utils.rb +26 -11
- data/lib/rack/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '078561a77beb0af3f12ba96b1a506598140482eec56592a6800e7bf14d5b57c9'
|
4
|
+
data.tar.gz: d14d73096818a28e4dc1e9e98309164029ba0c24768468c6299d11d11fe6a839
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 577296b45efdde2334fa386c57b6a9dcd8409cf8949875bcd78970041a078af1fa48e7cf030c6e4bf1377a7eecc771332aeec4c135df25ca74116ae56ab015de
|
7
|
+
data.tar.gz: f589a73eb2b74eea08499e4e945df139612619c1d6543edc0d8ebe78bb2b8181625464d607150a3ef89b86659f6a1bb1838a7940bd64bd418d2ac21873a067db
|
data/CHANGELOG.md
CHANGED
@@ -2,13 +2,49 @@
|
|
2
2
|
|
3
3
|
All notable changes to this project will be documented in this file. For info on how to format all future additions to this file please reference [Keep A Changelog](https://keepachangelog.com/en/1.0.0/).
|
4
4
|
|
5
|
+
## [2.2.6.4] - 2023-03-13
|
6
|
+
|
7
|
+
- [CVE-2023-27539] Avoid ReDoS in header parsing
|
8
|
+
|
9
|
+
## [2.2.6.3] - 2023-03-02
|
10
|
+
|
11
|
+
- [CVE-2023-27530] Introduce multipart_total_part_limit to limit total parts
|
12
|
+
|
13
|
+
## [2.2.6.2] - 2022-01-17
|
14
|
+
|
15
|
+
- [CVE-2022-44570] Fix ReDoS in Rack::Utils.get_byte_ranges
|
16
|
+
|
17
|
+
## [2.2.6.1] - 2022-01-17
|
18
|
+
|
19
|
+
- [CVE-2022-44571] Fix ReDoS vulnerability in multipart parser
|
20
|
+
- [CVE-2022-44572] Forbid control characters in attributes (also ReDoS)
|
21
|
+
|
22
|
+
## [2.2.6] - 2022-01-17
|
23
|
+
|
24
|
+
- Extend `Rack::MethodOverride` to handle `QueryParser::ParamsTooDeepError` error. ([#2011](https://github.com/rack/rack/pull/2011), [@byroot](https://github.com/byroot))
|
25
|
+
|
26
|
+
## [2.2.5] - 2022-12-27
|
27
|
+
|
28
|
+
### Fixed
|
29
|
+
|
30
|
+
- `Rack::URLMap` uses non-deprecated form of `Regexp.new`. ([#1998](https://github.com/rack/rack/pull/1998), [@weizheheng](https://github.com/weizheheng))
|
31
|
+
|
32
|
+
## [2.2.4] - 2022-06-30
|
33
|
+
|
34
|
+
- Better support for lower case headers in `Rack::ETag` middleware. ([#1919](https://github.com/rack/rack/pull/1919), [@ioquatix](https://github.com/ioquatix))
|
35
|
+
- Use custom exception on params too deep error. ([#1838](https://github.com/rack/rack/pull/1838), [@simi](https://github.com/simi))
|
36
|
+
|
5
37
|
## [2.2.3.1] - 2022-05-27
|
6
38
|
|
39
|
+
### Security
|
40
|
+
|
7
41
|
- [CVE-2022-30123] Fix shell escaping issue in Common Logger
|
8
42
|
- [CVE-2022-30122] Restrict parsing of broken MIME attachments
|
9
43
|
|
10
44
|
## [2.2.3] - 2020-02-11
|
11
45
|
|
46
|
+
### Security
|
47
|
+
|
12
48
|
- [CVE-2020-8184] Only decode cookie values
|
13
49
|
|
14
50
|
## [2.2.2] - 2020-02-11
|
data/README.rdoc
CHANGED
@@ -202,16 +202,30 @@ Limiting the depth prevents a possible stack overflow when parsing parameters.
|
|
202
202
|
|
203
203
|
Defaults to 100.
|
204
204
|
|
205
|
-
===
|
205
|
+
=== multipart_file_limit
|
206
206
|
|
207
|
-
The maximum number of parts a request can contain.
|
207
|
+
The maximum number of parts with a filename a request can contain.
|
208
208
|
Accepting too many part can lead to the server running out of file handles.
|
209
209
|
|
210
210
|
The default is 128, which means that a single request can't upload more than 128 files at once.
|
211
211
|
|
212
212
|
Set to 0 for no limit.
|
213
213
|
|
214
|
-
Can also be set via the +
|
214
|
+
Can also be set via the +RACK_MULTIPART_FILE_LIMIT+ environment variable.
|
215
|
+
|
216
|
+
(This is also aliased as +multipart_part_limit+ and +RACK_MULTIPART_PART_LIMIT+ for compatibility)
|
217
|
+
|
218
|
+
=== multipart_total_part_limit
|
219
|
+
|
220
|
+
The maximum total number of parts a request can contain of any type, including
|
221
|
+
both file and non-file form fields.
|
222
|
+
|
223
|
+
The default is 4096, which means that a single request can't contain more than
|
224
|
+
4096 parts.
|
225
|
+
|
226
|
+
Set to 0 for no limit.
|
227
|
+
|
228
|
+
Can also be set via the +RACK_MULTIPART_TOTAL_PART_LIMIT+ environment variable.
|
215
229
|
|
216
230
|
== Changelog
|
217
231
|
|
data/lib/rack/etag.rb
CHANGED
data/lib/rack/lint.rb
CHANGED
@@ -48,10 +48,10 @@ module Rack
|
|
48
48
|
|
49
49
|
## and returns an Array of exactly three values:
|
50
50
|
ary = @app.call(env)
|
51
|
-
assert("response
|
51
|
+
assert("response is not an Array, but #{ary.class}") {
|
52
52
|
ary.kind_of? Array
|
53
53
|
}
|
54
|
-
assert("response array
|
54
|
+
assert("response array has #{ary.size} elements instead of 3") {
|
55
55
|
ary.size == 3
|
56
56
|
}
|
57
57
|
|
data/lib/rack/method_override.rb
CHANGED
@@ -43,7 +43,7 @@ module Rack
|
|
43
43
|
|
44
44
|
def method_override_param(req)
|
45
45
|
req.POST[METHOD_OVERRIDE_PARAM_KEY]
|
46
|
-
rescue Utils::InvalidParameterError, Utils::ParameterTypeError
|
46
|
+
rescue Utils::InvalidParameterError, Utils::ParameterTypeError, QueryParser::ParamsTooDeepError
|
47
47
|
req.get_header(RACK_ERRORS).puts "Invalid or incomplete POST params"
|
48
48
|
rescue EOFError
|
49
49
|
req.get_header(RACK_ERRORS).puts "Bad request content body"
|
@@ -5,6 +5,7 @@ require 'strscan'
|
|
5
5
|
module Rack
|
6
6
|
module Multipart
|
7
7
|
class MultipartPartLimitError < Errno::EMFILE; end
|
8
|
+
class MultipartTotalPartLimitError < StandardError; end
|
8
9
|
|
9
10
|
class Parser
|
10
11
|
(require_relative '../core_ext/regexp'; using ::Rack::RegexpExtensions) if RUBY_VERSION < '2.4'
|
@@ -140,7 +141,7 @@ module Rack
|
|
140
141
|
|
141
142
|
@mime_parts[mime_index] = klass.new(body, head, filename, content_type, name)
|
142
143
|
|
143
|
-
|
144
|
+
check_part_limits
|
144
145
|
end
|
145
146
|
|
146
147
|
def on_mime_body(mime_index, content)
|
@@ -152,13 +153,23 @@ module Rack
|
|
152
153
|
|
153
154
|
private
|
154
155
|
|
155
|
-
def
|
156
|
-
|
157
|
-
|
156
|
+
def check_part_limits
|
157
|
+
file_limit = Utils.multipart_file_limit
|
158
|
+
part_limit = Utils.multipart_total_part_limit
|
159
|
+
|
160
|
+
if file_limit && file_limit > 0
|
161
|
+
if @open_files >= file_limit
|
158
162
|
@mime_parts.each(&:close)
|
159
163
|
raise MultipartPartLimitError, 'Maximum file multiparts in content reached'
|
160
164
|
end
|
161
165
|
end
|
166
|
+
|
167
|
+
if part_limit && part_limit > 0
|
168
|
+
if @mime_parts.size >= part_limit
|
169
|
+
@mime_parts.each(&:close)
|
170
|
+
raise MultipartTotalPartLimitError, 'Maximum total multiparts in content reached'
|
171
|
+
end
|
172
|
+
end
|
162
173
|
end
|
163
174
|
end
|
164
175
|
|
data/lib/rack/multipart.rb
CHANGED
@@ -18,10 +18,10 @@ module Rack
|
|
18
18
|
VALUE = /"(?:\\"|[^"])*"|#{TOKEN}/
|
19
19
|
BROKEN = /^#{CONDISP}.*;\s*filename=(#{VALUE})/i
|
20
20
|
MULTIPART_CONTENT_TYPE = /Content-Type: (.*)#{EOL}/ni
|
21
|
-
MULTIPART_CONTENT_DISPOSITION = /Content-Disposition
|
21
|
+
MULTIPART_CONTENT_DISPOSITION = /Content-Disposition:[^:]*;\s*name=(#{VALUE})/ni
|
22
22
|
MULTIPART_CONTENT_ID = /Content-ID:\s*([^#{EOL}]*)/ni
|
23
23
|
# Updated definitions from RFC 2231
|
24
|
-
ATTRIBUTE_CHAR = %r{[^ \
|
24
|
+
ATTRIBUTE_CHAR = %r{[^ \x00-\x1f\x7f)(><@,;:\\"/\[\]?='*%]}
|
25
25
|
ATTRIBUTE = /#{ATTRIBUTE_CHAR}+/
|
26
26
|
SECTION = /\*[0-9]+/
|
27
27
|
REGULAR_PARAMETER_NAME = /#{ATTRIBUTE}#{SECTION}?/
|
data/lib/rack/query_parser.rb
CHANGED
@@ -16,6 +16,10 @@ module Rack
|
|
16
16
|
# sequence.
|
17
17
|
class InvalidParameterError < ArgumentError; end
|
18
18
|
|
19
|
+
# ParamsTooDeepError is the error that is raised when params are recursively
|
20
|
+
# nested over the specified limit.
|
21
|
+
class ParamsTooDeepError < RangeError; end
|
22
|
+
|
19
23
|
def self.make_default(key_space_limit, param_depth_limit)
|
20
24
|
new Params, key_space_limit, param_depth_limit
|
21
25
|
end
|
@@ -81,7 +85,7 @@ module Rack
|
|
81
85
|
# the structural types represented by two different parameter names are in
|
82
86
|
# conflict, a ParameterTypeError is raised.
|
83
87
|
def normalize_params(params, name, v, depth)
|
84
|
-
raise
|
88
|
+
raise ParamsTooDeepError if depth <= 0
|
85
89
|
|
86
90
|
name =~ %r(\A[\[\]]*([^\[\]]+)\]*)
|
87
91
|
k = $1 || ''
|
@@ -168,7 +172,7 @@ module Rack
|
|
168
172
|
|
169
173
|
def []=(key, value)
|
170
174
|
@size += key.size if key && !@params.key?(key)
|
171
|
-
raise
|
175
|
+
raise ParamsTooDeepError, 'exceeded available parameter key space' if @size > @limit
|
172
176
|
@params[key] = value
|
173
177
|
end
|
174
178
|
|
data/lib/rack/request.rb
CHANGED
@@ -572,8 +572,8 @@ module Rack
|
|
572
572
|
end
|
573
573
|
|
574
574
|
def parse_http_accept_header(header)
|
575
|
-
header.to_s.split(
|
576
|
-
attribute, parameters = part.split(
|
575
|
+
header.to_s.split(",").each(&:strip!).map do |part|
|
576
|
+
attribute, parameters = part.split(";", 2).each(&:strip!)
|
577
577
|
quality = 1.0
|
578
578
|
if parameters and /\Aq=([\d.]+)/ =~ parameters
|
579
579
|
quality = $1.to_f
|
data/lib/rack/urlmap.rb
CHANGED
@@ -35,7 +35,7 @@ module Rack
|
|
35
35
|
end
|
36
36
|
|
37
37
|
location = location.chomp('/')
|
38
|
-
match = Regexp.new("^#{Regexp.quote(location).gsub('/', '/+')}(.*)",
|
38
|
+
match = Regexp.new("^#{Regexp.quote(location).gsub('/', '/+')}(.*)", Regexp::NOENCODING)
|
39
39
|
|
40
40
|
[host, location, match, app]
|
41
41
|
}.sort_by do |(host, location, _, _)|
|
data/lib/rack/utils.rb
CHANGED
@@ -22,6 +22,9 @@ module Rack
|
|
22
22
|
COMMON_SEP = QueryParser::COMMON_SEP
|
23
23
|
KeySpaceConstrainedParams = QueryParser::Params
|
24
24
|
|
25
|
+
RFC2822_DAY_NAME = [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ]
|
26
|
+
RFC2822_MONTH_NAME = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ]
|
27
|
+
|
25
28
|
class << self
|
26
29
|
attr_accessor :default_query_parser
|
27
30
|
end
|
@@ -55,13 +58,24 @@ module Rack
|
|
55
58
|
end
|
56
59
|
|
57
60
|
class << self
|
58
|
-
attr_accessor :
|
61
|
+
attr_accessor :multipart_total_part_limit
|
62
|
+
|
63
|
+
attr_accessor :multipart_file_limit
|
64
|
+
|
65
|
+
# multipart_part_limit is the original name of multipart_file_limit, but
|
66
|
+
# the limit only counts parts with filenames.
|
67
|
+
alias multipart_part_limit multipart_file_limit
|
68
|
+
alias multipart_part_limit= multipart_file_limit=
|
59
69
|
end
|
60
70
|
|
61
|
-
# The maximum number of parts a request can contain. Accepting too
|
62
|
-
# can lead to the server running out of file handles.
|
71
|
+
# The maximum number of file parts a request can contain. Accepting too
|
72
|
+
# many parts can lead to the server running out of file handles.
|
63
73
|
# Set to `0` for no limit.
|
64
|
-
self.
|
74
|
+
self.multipart_file_limit = (ENV['RACK_MULTIPART_PART_LIMIT'] || ENV['RACK_MULTIPART_FILE_LIMIT'] || 128).to_i
|
75
|
+
|
76
|
+
# The maximum total number of parts a request can contain. Accepting too
|
77
|
+
# many can lead to excessive memory use and parsing time.
|
78
|
+
self.multipart_total_part_limit = (ENV['RACK_MULTIPART_TOTAL_PART_LIMIT'] || 4096).to_i
|
65
79
|
|
66
80
|
def self.param_depth_limit
|
67
81
|
default_query_parser.param_depth_limit
|
@@ -327,8 +341,8 @@ module Rack
|
|
327
341
|
# weekday and month.
|
328
342
|
#
|
329
343
|
def rfc2109(time)
|
330
|
-
wday =
|
331
|
-
mon =
|
344
|
+
wday = RFC2822_DAY_NAME[time.wday]
|
345
|
+
mon = RFC2822_MONTH_NAME[time.mon - 1]
|
332
346
|
time.strftime("#{wday}, %d-#{mon}-%Y %H:%M:%S GMT")
|
333
347
|
end
|
334
348
|
|
@@ -345,17 +359,18 @@ module Rack
|
|
345
359
|
return nil unless http_range && http_range =~ /bytes=([^;]+)/
|
346
360
|
ranges = []
|
347
361
|
$1.split(/,\s*/).each do |range_spec|
|
348
|
-
return nil
|
349
|
-
|
350
|
-
|
351
|
-
|
362
|
+
return nil unless range_spec.include?('-')
|
363
|
+
range = range_spec.split('-')
|
364
|
+
r0, r1 = range[0], range[1]
|
365
|
+
if r0.nil? || r0.empty?
|
366
|
+
return nil if r1.nil?
|
352
367
|
# suffix-byte-range-spec, represents trailing suffix of file
|
353
368
|
r0 = size - r1.to_i
|
354
369
|
r0 = 0 if r0 < 0
|
355
370
|
r1 = size - 1
|
356
371
|
else
|
357
372
|
r0 = r0.to_i
|
358
|
-
if r1.
|
373
|
+
if r1.nil?
|
359
374
|
r1 = size - 1
|
360
375
|
else
|
361
376
|
r1 = r1.to_i
|
data/lib/rack/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.2.
|
4
|
+
version: 2.2.6.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Leah Neukirchen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-03-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|