rack 3.1.15 → 3.1.17
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 +4 -4
- data/CHANGELOG.md +45 -2
- data/README.md +8 -0
- data/lib/rack/multipart/parser.rb +57 -5
- 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: 14e5b5eb8c607ee4b9a8904f54237a1e09bd849e4c92f8654def11d9979d8e92
|
4
|
+
data.tar.gz: d2d6df191d236142e93d984bfd81a2c6cc7ec9904660a8974424d6c7f133fc49
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c69d56a89d655e1de73db0096ceb060c4c70da8d074988a233f2b3102cfe1b2e2ed0eb3e4cb08ddf83ed0179ee25e91d43f609088d4ad46c5cd469e27ed02421
|
7
|
+
data.tar.gz: 81de2ad1d0e1838791934f46ec3c144f4253c99e34d60276003fe382febcbdecb5c253553d5972521044342404e9805591a8223b3f3ba6ee8f027e33631e929c
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,20 @@
|
|
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
|
+
## [3.1.17] - 2025-10-07
|
6
|
+
|
7
|
+
### Security
|
8
|
+
|
9
|
+
- [CVE-2025-61772](https://github.com/advisories/GHSA-wpv5-97wm-hp9c) Multipart parser buffers unbounded per-part headers, enabling DoS (memory exhaustion)
|
10
|
+
- [CVE-2025-61771](https://github.com/advisories/GHSA-w9pc-fmgc-vxvw) Multipart parser buffers large non‑file fields entirely in memory, enabling DoS (memory exhaustion)
|
11
|
+
- [CVE-2025-61770](https://github.com/advisories/GHSA-p543-xpfm-54cp) Unbounded multipart preamble buffering enables DoS (memory exhaustion)
|
12
|
+
|
13
|
+
## [3.1.16] - 2025-06-04
|
14
|
+
|
15
|
+
### Security
|
16
|
+
|
17
|
+
- [CVE-2025-49007](https://github.com/advisories/GHSA-47m2-26rw-j2jw) Fix ReDoS in multipart request.
|
18
|
+
|
5
19
|
## [3.1.15] - 2025-05-18
|
6
20
|
|
7
21
|
- Optional support for `CGI::Cookie` if not available. ([#2327](https://github.com/rack/rack/pull/2327), [#2333](https://github.com/rack/rack/pull/2333), [@earlopain])
|
@@ -143,11 +157,14 @@ Rack v3.1 is primarily a maintenance release that removes features deprecated in
|
|
143
157
|
|
144
158
|
- In `Rack::Files`, ignore the `Range` header if served file is 0 bytes. ([#2159](https://github.com/rack/rack/pull/2159), [@zarqman])
|
145
159
|
|
160
|
+
## [3.0.18] - 2025-05-22
|
161
|
+
|
162
|
+
- Fix incorrect backport of optional `CGI::Cookie` support. ([#2335](https://github.com/rack/rack/pull/2335), [@jeremyevans])
|
163
|
+
|
146
164
|
## [3.0.17] - 2025-05-18
|
147
165
|
|
148
166
|
- Optional support for `CGI::Cookie` if not available. ([#2327](https://github.com/rack/rack/pull/2327), [#2333](https://github.com/rack/rack/pull/2333), [@earlopain])
|
149
167
|
|
150
|
-
|
151
168
|
## [3.0.16] - 2025-05-06
|
152
169
|
|
153
170
|
### Security
|
@@ -170,6 +187,10 @@ Rack v3.1 is primarily a maintenance release that removes features deprecated in
|
|
170
187
|
|
171
188
|
- [CVE-2025-27111](https://github.com/rack/rack/security/advisories/GHSA-8cgq-6mh2-7j6v) Possible Log Injection in `Rack::Sendfile`.
|
172
189
|
|
190
|
+
### Fixed
|
191
|
+
|
192
|
+
- Remove autoloads for constants no longer shipped with Rack. ([#2269](https://github.com/rack/rack/pull/2269), [@ccutrer](https://github.com/ccutrer))
|
193
|
+
|
173
194
|
## [3.0.12] - 2025-02-12
|
174
195
|
|
175
196
|
### Security
|
@@ -304,7 +325,7 @@ Rack v3.1 is primarily a maintenance release that removes features deprecated in
|
|
304
325
|
- Remove deprecated Rack::Request::SCHEME_WHITELIST. ([@jeremyevans])
|
305
326
|
- Remove internal cookie deletion using pattern matching, there are very few practical cases where it would be useful and browsers handle it correctly without us doing anything special. ([#1844](https://github.com/rack/rack/pull/1844), [@ioquatix])
|
306
327
|
- Remove `rack.version` as it comes too late to be useful. ([#1938](https://github.com/rack/rack/pull/1938), [@ioquatix])
|
307
|
-
- Extract `rackup` command, `Rack::Server`, `Rack::Handler
|
328
|
+
- Extract `rackup` command, `Rack::Server`, `Rack::Handler` and related code into a separate gem. ([#1937](https://github.com/rack/rack/pull/1937), [@ioquatix])
|
308
329
|
|
309
330
|
### Added
|
310
331
|
|
@@ -352,6 +373,28 @@ Rack v3.1 is primarily a maintenance release that removes features deprecated in
|
|
352
373
|
- Fix multipart filename generation for filenames that contain spaces. Encode spaces as "%20" instead of "+" which will be decoded properly by the multipart parser. ([#1736](https://github.com/rack/rack/pull/1645), [@muirdm](https://github.com/muirdm))
|
353
374
|
- `Rack::Request#scheme` returns `ws` or `wss` when one of the `X-Forwarded-Scheme` / `X-Forwarded-Proto` headers is set to `ws` or `wss`, respectively. ([#1730](https://github.com/rack/rack/issues/1730), [@erwanst](https://github.com/erwanst))
|
354
375
|
|
376
|
+
## [2.2.19] - 2025-10-07
|
377
|
+
|
378
|
+
### Security
|
379
|
+
|
380
|
+
- [CVE-2025-61772](https://github.com/advisories/GHSA-wpv5-97wm-hp9c) Multipart parser buffers unbounded per-part headers, enabling DoS (memory exhaustion)
|
381
|
+
- [CVE-2025-61771](https://github.com/advisories/GHSA-w9pc-fmgc-vxvw) Multipart parser buffers large non‑file fields entirely in memory, enabling DoS (memory exhaustion)
|
382
|
+
- [CVE-2025-61770](https://github.com/advisories/GHSA-p543-xpfm-54cp) Unbounded multipart preamble buffering enables DoS (memory exhaustion)
|
383
|
+
|
384
|
+
## [2.2.18] - 2025-09-25
|
385
|
+
|
386
|
+
### Security
|
387
|
+
|
388
|
+
- [CVE-2025-59830](https://github.com/rack/rack/security/advisories/GHSA-625h-95r8-8xpm) Unbounded parameter parsing in `Rack::QueryParser` can lead to memory exhaustion via semicolon-separated parameters.
|
389
|
+
|
390
|
+
## [2.2.17] - 2025-06-03
|
391
|
+
|
392
|
+
- Backport `Rack::MediaType#params` now handles parameters without values. ([#2263](https://github.com/rack/rack/pull/2263), [@AllyMarthaJ](https://github.com/AllyMarthaJ))
|
393
|
+
|
394
|
+
## [2.2.16] - 2025-05-22
|
395
|
+
|
396
|
+
- Fix incorrect backport of optional `CGI::Cookie` support. ([#2335](https://github.com/rack/rack/pull/2335), [@jeremyevans])
|
397
|
+
|
355
398
|
## [2.2.15] - 2025-05-18
|
356
399
|
|
357
400
|
- Optional support for `CGI::Cookie` if not available. ([#2327](https://github.com/rack/rack/pull/2327), [#2333](https://github.com/rack/rack/pull/2333), [@earlopain])
|
data/README.md
CHANGED
@@ -210,6 +210,14 @@ query string, before attempting parsing, so if the same parameter key is
|
|
210
210
|
used multiple times in the query, each counts as a separate parameter for
|
211
211
|
this check.
|
212
212
|
|
213
|
+
### `RACK_MULTIPART_BUFFERED_UPLOAD_BYTESIZE_LIMIT`
|
214
|
+
|
215
|
+
This environment variable sets the maximum amount of memory Rack will use
|
216
|
+
to buffer multipart parameters when parsing a request body. This considers
|
217
|
+
the size of the multipart mime headers and the body part for multipart
|
218
|
+
parameters that are buffered in memory and do not use tempfiles. This
|
219
|
+
defaults to 16MB if not provided.
|
220
|
+
|
213
221
|
### `param_depth_limit`
|
214
222
|
|
215
223
|
```ruby
|
@@ -31,10 +31,12 @@ module Rack
|
|
31
31
|
Error = BoundaryTooLongError
|
32
32
|
|
33
33
|
EOL = "\r\n"
|
34
|
+
FWS = /[ \t]+(?:\r\n[ \t]+)?/ # whitespace with optional folding
|
35
|
+
HEADER_VALUE = "(?:[^\r\n]|\r\n[ \t])*" # anything but a non-folding CRLF
|
34
36
|
MULTIPART = %r|\Amultipart/.*boundary=\"?([^\";,]+)\"?|ni
|
35
|
-
MULTIPART_CONTENT_TYPE =
|
36
|
-
MULTIPART_CONTENT_DISPOSITION =
|
37
|
-
MULTIPART_CONTENT_ID =
|
37
|
+
MULTIPART_CONTENT_TYPE = /^Content-Type:#{FWS}?(#{HEADER_VALUE})/ni
|
38
|
+
MULTIPART_CONTENT_DISPOSITION = /^Content-Disposition:#{FWS}?(#{HEADER_VALUE})/ni
|
39
|
+
MULTIPART_CONTENT_ID = /^Content-ID:#{FWS}?(#{HEADER_VALUE})/ni
|
38
40
|
|
39
41
|
class Parser
|
40
42
|
BUFSIZE = 1_048_576
|
@@ -45,6 +47,27 @@ module Rack
|
|
45
47
|
Tempfile.new(["RackMultipart", extension])
|
46
48
|
}
|
47
49
|
|
50
|
+
BOUNDARY_START_LIMIT = 16 * 1024
|
51
|
+
private_constant :BOUNDARY_START_LIMIT
|
52
|
+
|
53
|
+
MIME_HEADER_BYTESIZE_LIMIT = 64 * 1024
|
54
|
+
private_constant :MIME_HEADER_BYTESIZE_LIMIT
|
55
|
+
|
56
|
+
env_int = lambda do |key, val|
|
57
|
+
if str_val = ENV[key]
|
58
|
+
begin
|
59
|
+
val = Integer(str_val, 10)
|
60
|
+
rescue ArgumentError
|
61
|
+
raise ArgumentError, "non-integer value provided for environment variable #{key}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
val
|
66
|
+
end
|
67
|
+
|
68
|
+
BUFFERED_UPLOAD_BYTESIZE_LIMIT = env_int.call("RACK_MULTIPART_BUFFERED_UPLOAD_BYTESIZE_LIMIT", 16 * 1024 * 1024)
|
69
|
+
private_constant :BUFFERED_UPLOAD_BYTESIZE_LIMIT
|
70
|
+
|
48
71
|
class BoundedIO # :nodoc:
|
49
72
|
def initialize(io, content_length)
|
50
73
|
@io = io
|
@@ -204,6 +227,8 @@ module Rack
|
|
204
227
|
|
205
228
|
@state = :FAST_FORWARD
|
206
229
|
@mime_index = 0
|
230
|
+
@body_retained = nil
|
231
|
+
@retained_size = 0
|
207
232
|
@collector = Collector.new tempfile
|
208
233
|
|
209
234
|
@sbuf = StringScanner.new("".dup)
|
@@ -285,6 +310,10 @@ module Rack
|
|
285
310
|
|
286
311
|
# retry for opening boundary
|
287
312
|
else
|
313
|
+
# We raise if we don't find the multipart boundary, to avoid unbounded memory
|
314
|
+
# buffering. Note that the actual limit is the higher of 16KB and the buffer size (1MB by default)
|
315
|
+
raise Error, "multipart boundary not found within limit" if @sbuf.string.bytesize > BOUNDARY_START_LIMIT
|
316
|
+
|
288
317
|
# no boundary found, keep reading data
|
289
318
|
return :want_read
|
290
319
|
end
|
@@ -401,16 +430,30 @@ module Rack
|
|
401
430
|
name = filename || "#{content_type || TEXT_PLAIN}[]".dup
|
402
431
|
end
|
403
432
|
|
433
|
+
# Mime part head data is retained for both TempfilePart and BufferPart
|
434
|
+
# for the entireity of the parse, even though it isn't used for BufferPart.
|
435
|
+
update_retained_size(head.bytesize)
|
436
|
+
|
437
|
+
# If a filename is given, a TempfilePart will be used, so the body will
|
438
|
+
# not be buffered in memory. However, if a filename is not given, a BufferPart
|
439
|
+
# will be used, and the body will be buffered in memory.
|
440
|
+
@body_retained = !filename
|
441
|
+
|
404
442
|
@collector.on_mime_head @mime_index, head, filename, content_type, name
|
405
443
|
@state = :MIME_BODY
|
406
444
|
else
|
407
|
-
|
445
|
+
# We raise if the mime part header is too large, to avoid unbounded memory
|
446
|
+
# buffering. Note that the actual limit is the higher of 64KB and the buffer size (1MB by default)
|
447
|
+
raise Error, "multipart mime part header too large" if @sbuf.string.bytesize > MIME_HEADER_BYTESIZE_LIMIT
|
448
|
+
|
449
|
+
return :want_read
|
408
450
|
end
|
409
451
|
end
|
410
452
|
|
411
453
|
def handle_mime_body
|
412
454
|
if (body_with_boundary = @sbuf.check_until(@body_regex)) # check but do not advance the pointer yet
|
413
455
|
body = body_with_boundary.sub(@body_regex_at_end, '') # remove the boundary from the string
|
456
|
+
update_retained_size(body.bytesize) if @body_retained
|
414
457
|
@collector.on_mime_body @mime_index, body
|
415
458
|
@sbuf.pos += body.length + 2 # skip \r\n after the content
|
416
459
|
@state = :CONSUME_TOKEN
|
@@ -419,7 +462,9 @@ module Rack
|
|
419
462
|
# Save what we have so far
|
420
463
|
if @rx_max_size < @sbuf.rest_size
|
421
464
|
delta = @sbuf.rest_size - @rx_max_size
|
422
|
-
|
465
|
+
body = @sbuf.peek(delta)
|
466
|
+
update_retained_size(body.bytesize) if @body_retained
|
467
|
+
@collector.on_mime_body @mime_index, body
|
423
468
|
@sbuf.pos += delta
|
424
469
|
@sbuf.string = @sbuf.rest
|
425
470
|
end
|
@@ -427,6 +472,13 @@ module Rack
|
|
427
472
|
end
|
428
473
|
end
|
429
474
|
|
475
|
+
def update_retained_size(size)
|
476
|
+
@retained_size += size
|
477
|
+
if @retained_size > BUFFERED_UPLOAD_BYTESIZE_LIMIT
|
478
|
+
raise Error, "multipart data over retained size limit"
|
479
|
+
end
|
480
|
+
end
|
481
|
+
|
430
482
|
# Scan until the we find the start or end of the boundary.
|
431
483
|
# If we find it, return the appropriate symbol for the start or
|
432
484
|
# end of the boundary. If we don't find the start or end of the
|
data/lib/rack/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.1.
|
4
|
+
version: 3.1.17
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Leah Neukirchen
|
@@ -156,7 +156,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
156
156
|
- !ruby/object:Gem::Version
|
157
157
|
version: '0'
|
158
158
|
requirements: []
|
159
|
-
rubygems_version: 3.6.
|
159
|
+
rubygems_version: 3.6.9
|
160
160
|
specification_version: 4
|
161
161
|
summary: A modular Ruby webserver interface.
|
162
162
|
test_files: []
|