rack 2.2.24 → 2.2.25

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
2
  SHA256:
3
- metadata.gz: 5905364bd5b40d622e2e10330911370ec92f23e5afa1aa58283c2f0cf9a5782d
4
- data.tar.gz: '09c4da33251a32194f0a656767150eaa17367f8e42ee45735971e963d0e43991'
3
+ metadata.gz: c5322ca41af487959f08981c9964d7ef877f82b0ee4374e4338bedbeb93d3538
4
+ data.tar.gz: 4accf7c52defac80efd55caef60ef967f1a813743d8487723e733f66591fce5d
5
5
  SHA512:
6
- metadata.gz: 5ee4b678c01a6bb97074b87886498d8aa3bce9b61322cb95cc7908dec5e751fdfb8b238bc98956719505b394de21d1f6787d2593378b1fee4a6fe10b9aea3d5b
7
- data.tar.gz: 032c32c7ebb220355578577fce8ad49c67f869b0ba60e533c3e1178b3265086d50e34de0912f00dc9bfdfb4042d446bc2b1ac8bc62916835521b4cf3786de341
6
+ metadata.gz: 4b5cedb21343a2e062ca5daf8c55f88fe29bc7d884244dcd13ca6cad858e61764b18f71ea93cfb6a538bc03dadbb82ad7471895d1f6cbc1b2bc727651a807a11
7
+ data.tar.gz: 5bc5a948d20e77d1c831173b4ba5ba5b661bc985f60a6bf9fd1224033c6725ed2c8753f39766a3fe386b56457de9439ace3459cd0f1f650dd0c7fdb2effdcc13
data/CHANGELOG.md CHANGED
@@ -2,6 +2,18 @@
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.25] - 2026-10-30
6
+
7
+ ### Security
8
+
9
+ - [GHSA-5v64-555j-wjxm](https://github.com/advisories/GHSA-5v64-555j-wjxm) Multipart parser retains parsed data in its scan buffer, allowing denial of service via memory exhaustion.
10
+ - [GHSA-wvg4-6p58-3gh3](https://github.com/advisories/GHSA-wvg4-6p58-3gh3) `Rack::Static` header rules were matched against an unnormalized path, allowing dot segments to bypass them.
11
+ - [GHSA-p8x9-v4hv-2w4g](https://github.com/advisories/GHSA-p8x9-v4hv-2w4g) Multipart requests with more than one `boundary` parameter were accepted when the first value was empty or began with a quote, semicolon, or comma, bypassing the guard added for CVE-2026-26961.
12
+
13
+ ### Fixed
14
+
15
+ - Multipart parser: scan boundary lines with a literal newline search instead of a backtracking regexp, which allocated tens of megabytes per scan for long lines and made the scan buffer fix above ineffective on this series.
16
+
5
17
  ## [2.2.24] - 2026-08-13
6
18
 
7
19
  ### Security
@@ -20,6 +20,9 @@ module Rack
20
20
 
21
21
  BOUNDARY_REGEX = /\A([^\n]*(?:\n|\Z))/
22
22
 
23
+ LINE_END = /\n/
24
+ private_constant :LINE_END
25
+
23
26
  BOUNDARY_START_LIMIT = 16 * 1024
24
27
  private_constant :BOUNDARY_START_LIMIT
25
28
 
@@ -93,7 +96,11 @@ module Rack
93
96
  unless data[1].empty?
94
97
  raise EOFError, "whitespace between boundary parameter name and equal sign"
95
98
  end
96
- if data.post_match =~ /boundary\s*=/i
99
+ # Count across the whole header rather than only after the match: the
100
+ # lazy prefix in MULTIPART can skip a first boundary parameter whose
101
+ # value is empty or starts with a quote, semicolon, or comma. Also
102
+ # count RFC 2231 boundary* parameters, which some parsers prefer.
103
+ if content_type.scan(/boundary(?:\*\d*\*?)?\s*=/i).size > 1
97
104
  raise EOFError, "multiple boundary parameters found in multipart content type"
98
105
  end
99
106
 
@@ -346,6 +353,7 @@ module Rack
346
353
  # buffering. Note that the actual limit is the higher of 64KB and the buffer size (1MB by default)
347
354
  raise EOFError, "multipart mime part header too large" if @sbuf.rest.bytesize > MIME_HEADER_BYTESIZE_LIMIT
348
355
 
356
+ @sbuf.string = @sbuf.rest
349
357
  return :want_read
350
358
  end
351
359
  end
@@ -366,8 +374,8 @@ module Rack
366
374
  update_retained_size(body.bytesize) if @body_retained
367
375
  @collector.on_mime_body @mime_index, body
368
376
  @sbuf.pos += delta
369
- @sbuf.string = @sbuf.rest
370
377
  end
378
+ @sbuf.string = @sbuf.rest
371
379
  :want_read
372
380
  end
373
381
  end
@@ -386,7 +394,7 @@ module Rack
386
394
  # end of the boundary. If we don't find the start or end of the
387
395
  # boundary, clear the buffer and return nil.
388
396
  def consume_boundary
389
- while read_buffer = @sbuf.scan_until(BOUNDARY_REGEX)
397
+ while read_buffer = scan_line
390
398
  case read_buffer.strip
391
399
  when full_boundary then return :BOUNDARY
392
400
  when @end_boundary then return :END_BOUNDARY
@@ -395,6 +403,21 @@ module Rack
395
403
  end
396
404
  end
397
405
 
406
+ # Return the next line of the buffer including its trailing "\n", or the
407
+ # rest of the buffer if it contains no "\n", and advance past it. This is
408
+ # equivalent to `@sbuf.scan_until(BOUNDARY_REGEX)`, but searching for the
409
+ # "\n" directly avoids the regexp engine's backtracking stack, which grows
410
+ # by one entry per byte matched by `[^\n]*` (tens of MB for a 1 MB line).
411
+ def scan_line
412
+ if line = @sbuf.scan_until(LINE_END)
413
+ line
414
+ else
415
+ line = @sbuf.rest
416
+ @sbuf.terminate
417
+ line
418
+ end
419
+ end
420
+
398
421
  def get_filename(head)
399
422
  filename = nil
400
423
  case head
data/lib/rack/static.rb CHANGED
@@ -168,7 +168,7 @@ module Rack
168
168
 
169
169
  # Convert HTTP header rules to HTTP headers
170
170
  def applicable_rules(path)
171
- path = ::Rack::Utils.unescape_path(path)
171
+ path = ::Rack::Utils.clean_path_info(::Rack::Utils.unescape_path(path))
172
172
 
173
173
  @header_rules.find_all do |rule, new_headers|
174
174
  case rule
data/lib/rack/version.rb CHANGED
@@ -20,7 +20,7 @@ module Rack
20
20
  VERSION.join(".")
21
21
  end
22
22
 
23
- RELEASE = "2.2.24"
23
+ RELEASE = "2.2.25"
24
24
 
25
25
  # Return the Rack release as a dotted string.
26
26
  def self.release
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: 2.2.24
4
+ version: 2.2.25
5
5
  platform: ruby
6
6
  authors:
7
7
  - Leah Neukirchen