diff --git a/CVE-2025-61770.patch b/CVE-2025-61770.patch deleted file mode 100644 index 740aaeaf6f8bf29bc0a132931b4bc31fa3a83532..0000000000000000000000000000000000000000 --- a/CVE-2025-61770.patch +++ /dev/null @@ -1,40 +0,0 @@ -diff --git a/lib/rack/multipart/parser.rb b/lib/rack/multipart/parser.rb -index c78f0e3..ca79607 100644 ---- a/lib/rack/multipart/parser.rb -+++ b/lib/rack/multipart/parser.rb -@@ -47,6 +47,12 @@ module Rack - Tempfile.new(["RackMultipart", extension]) - } - -+ BOUNDARY_START_LIMIT = 16 * 1024 -+ private_constant :BOUNDARY_START_LIMIT -+ -+ MIME_HEADER_BYTESIZE_LIMIT = 64 * 1024 -+ private_constant :MIME_HEADER_BYTESIZE_LIMIT -+ - class BoundedIO # :nodoc: - def initialize(io, content_length) - @io = io -@@ -287,6 +293,10 @@ module Rack - - # retry for opening boundary - else -+ # We raise if we don't find the multipart boundary, to avoid unbounded memory -+ # buffering. Note that the actual limit is the higher of 16KB and the buffer size (1MB by default) -+ raise Error, "multipart boundary not found within limit" if @sbuf.string.bytesize > BOUNDARY_START_LIMIT -+ - # no boundary found, keep reading data - return :want_read - end -@@ -406,7 +416,11 @@ module Rack - @collector.on_mime_head @mime_index, head, filename, content_type, name - @state = :MIME_BODY - else -- :want_read -+ # We raise if the mime part header is too large, to avoid unbounded memory -+ # buffering. Note that the actual limit is the higher of 64KB and the buffer size (1MB by default) -+ raise Error, "multipart mime part header too large" if @sbuf.string.bytesize > MIME_HEADER_BYTESIZE_LIMIT -+ -+ return :want_read - end - end diff --git a/CVE-2025-61771.patch b/CVE-2025-61771.patch deleted file mode 100644 index 31fa1f738ee30e5efe98a1847faca560f265c998..0000000000000000000000000000000000000000 --- a/CVE-2025-61771.patch +++ /dev/null @@ -1,84 +0,0 @@ -diff --git a/lib/rack/multipart/parser.rb b/lib/rack/multipart/parser.rb -index ca79607e6..81c91ad6d 100644 ---- a/lib/rack/multipart/parser.rb -+++ b/lib/rack/multipart/parser.rb -@@ -53,6 +53,21 @@ class Parser - MIME_HEADER_BYTESIZE_LIMIT = 64 * 1024 - private_constant :MIME_HEADER_BYTESIZE_LIMIT - -+ env_int = lambda do |key, val| -+ if str_val = ENV[key] -+ begin -+ val = Integer(str_val, 10) -+ rescue ArgumentError -+ raise ArgumentError, "non-integer value provided for environment variable #{key}" -+ end -+ end -+ -+ val -+ end -+ -+ BUFFERED_UPLOAD_BYTESIZE_LIMIT = env_int.call("RACK_MULTIPART_BUFFERED_UPLOAD_BYTESIZE_LIMIT", 16 * 1024 * 1024) -+ private_constant :BUFFERED_UPLOAD_BYTESIZE_LIMIT -+ - class BoundedIO # :nodoc: - def initialize(io, content_length) - @io = io -@@ -212,6 +227,8 @@ def initialize(boundary, tempfile, bufsize, query_parser) - - @state = :FAST_FORWARD - @mime_index = 0 -+ @body_retained = nil -+ @retained_size = 0 - @collector = Collector.new tempfile - - @sbuf = StringScanner.new("".dup) -@@ -413,6 +430,15 @@ def handle_mime_head - name = filename || "#{content_type || TEXT_PLAIN}[]".dup - end - -+ # Mime part head data is retained for both TempfilePart and BufferPart -+ # for the entireity of the parse, even though it isn't used for BufferPart. -+ update_retained_size(head.bytesize) -+ -+ # If a filename is given, a TempfilePart will be used, so the body will -+ # not be buffered in memory. However, if a filename is not given, a BufferPart -+ # will be used, and the body will be buffered in memory. -+ @body_retained = !filename -+ - @collector.on_mime_head @mime_index, head, filename, content_type, name - @state = :MIME_BODY - else -@@ -427,6 +453,7 @@ def handle_mime_head - def handle_mime_body - if (body_with_boundary = @sbuf.check_until(@body_regex)) # check but do not advance the pointer yet - body = body_with_boundary.sub(@body_regex_at_end, '') # remove the boundary from the string -+ update_retained_size(body.bytesize) if @body_retained - @collector.on_mime_body @mime_index, body - @sbuf.pos += body.length + 2 # skip \r\n after the content - @state = :CONSUME_TOKEN -@@ -435,7 +462,9 @@ def handle_mime_body - # Save what we have so far - if @rx_max_size < @sbuf.rest_size - delta = @sbuf.rest_size - @rx_max_size -- @collector.on_mime_body @mime_index, @sbuf.peek(delta) -+ body = @sbuf.peek(delta) -+ update_retained_size(body.bytesize) if @body_retained -+ @collector.on_mime_body @mime_index, body - @sbuf.pos += delta - @sbuf.string = @sbuf.rest - end -@@ -443,6 +472,13 @@ def handle_mime_body - end - end - -+ def update_retained_size(size) -+ @retained_size += size -+ if @retained_size > BUFFERED_UPLOAD_BYTESIZE_LIMIT -+ raise Error, "multipart data over retained size limit" -+ end -+ end -+ - # Scan until the we find the start or end of the boundary. - # If we find it, return the appropriate symbol for the start or - # end of the boundary. If we don't find the start or end of the diff --git a/CVE-2025-61919.patch b/CVE-2025-61919.patch deleted file mode 100644 index 327f4b8f8a0a5e805bb1ae59e11c387a6590ae3a..0000000000000000000000000000000000000000 --- a/CVE-2025-61919.patch +++ /dev/null @@ -1,38 +0,0 @@ -diff --git a/lib/rack/query_parser.rb b/lib/rack/query_parser.rb -index 3107e21..aa57759 100644 ---- a/lib/rack/query_parser.rb -+++ b/lib/rack/query_parser.rb -@@ -57,6 +57,8 @@ module Rack - PARAMS_LIMIT = env_int.call("RACK_QUERY_PARSER_PARAMS_LIMIT", 4096) - private_constant :PARAMS_LIMIT - -+ attr_reader :bytesize_limit -+ - def initialize(params_class, param_depth_limit, bytesize_limit: BYTESIZE_LIMIT, params_limit: PARAMS_LIMIT) - @params_class = params_class - @param_depth_limit = param_depth_limit -@@ -218,7 +220,7 @@ module Rack - def check_query_string(qs, sep) - if qs - if qs.bytesize > @bytesize_limit -- raise QueryLimitError, "total query size (#{qs.bytesize}) exceeds limit (#{@bytesize_limit})" -+ raise QueryLimitError, "total query size exceeds limit (#{@bytesize_limit})" - end - - if (param_count = qs.count(sep.is_a?(String) ? sep : '&')) >= @params_limit -diff --git a/lib/rack/request.rb b/lib/rack/request.rb -index 93526a0..007437b 100644 ---- a/lib/rack/request.rb -+++ b/lib/rack/request.rb -@@ -528,7 +528,10 @@ module Rack - set_header RACK_REQUEST_FORM_PAIRS, pairs - set_header RACK_REQUEST_FORM_HASH, expand_param_pairs(pairs) - else -- form_vars = get_header(RACK_INPUT).read -+ # Add 2 bytes. One to check whether it is over the limit, and a second -+ # in case the slice! call below removes the last byte -+ # If read returns nil, use the empty string -+ form_vars = get_header(RACK_INPUT).read(query_parser.bytesize_limit + -2) || '' - - # Fix for Safari Ajax postings that always append \0 - # form_vars.sub!(/\0\z/, '') # performance replacement: diff --git a/rubygem-rack.spec b/rubygem-rack.spec index d36766a2acfc55e2b55740dbfdd108616f0d97d2..33565895b9b6bdb3d7312b2f067759d061f3d4c1 100644 --- a/rubygem-rack.spec +++ b/rubygem-rack.spec @@ -1,17 +1,14 @@ %global gem_name rack Name: rubygem-%{gem_name} -Version: 3.1.16 -Release: 4%{?dist} +Version: 3.1.21 +Release: 1%{?dist} Summary: A modular Ruby webserver interface License: MIT AND BSD-3-Clause URL: https://github.com/rack/rack Source0: https://rubygems.org/gems/%{gem_name}-%{version}.gem Source1: rack-%{version}-tests.tar.gz -Patch0: CVE-2025-61770.patch -Patch1: CVE-2025-61771.patch -Patch2: CVE-2025-61919.patch BuildRequires: ruby(release) BuildRequires: rubygems-devel @@ -39,9 +36,6 @@ Documentation for %{name}. %prep %setup -q -n %{gem_name}-%{version} -b 1 -%patch0 -p1 -%patch1 -p1 -%patch2 -p1 @@ -85,6 +79,10 @@ ruby -Itest -e 'Dir.glob "./test/spec_*.rb", &method(:require)' || true %doc %{gem_instdir}/SPEC.rdoc %changelog +* Sun Apr 26 2026 zeyouliu - 3.1.21-1 +- [Type] security +- [DESC] Upgrade to version 3.1.21 to fix cves + * Thu Oct 16 2025 zeyouliu - 3.1.16-4 - [Type] security - [DESC] fix CVE-2025-61919 diff --git a/sources b/sources index a4e1c1b971312ac6bda184399d217300cdaad208..8ccce044b09148bf844e304c22b0dfb5f71bb880 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (rack-3.1.16-tests.tar.gz) = 8b6a09ea6a54c4c2fe51dd8b4c6cc0bdc689df0a6635897a761b616b78645546fdd94405b4ad60d56daadb70c578154e44ac1191d44fcd5dfae7989dc83cc7fe -SHA512 (rack-3.1.16.gem) = 65d8863d2d33a3ce5106cd8ac647389133eab0acfe5fa0cb02dff246313fdbc726c89f495c73e814258694b22508736958170d114edce8b7c15b7c444c7dcaa0 +SHA512 (rack-3.1.21-tests.tar.gz) = 67cbaf80272b3c187526ae0c15ec54545e0197b6c7a82b2010bacab05fe35f67faf0f1ec1b8c79caf473130b1e45add49e5bd5d93f24a9497e7b37a068fd41c2 +SHA512 (rack-3.1.21.gem) = 86ffc5067c59cf621a1629484cd73c1d19d6591e7b1dec4cca778a9339ce170975fbc2fd526c97fc61c89be3f653f74fc0e9ecc42918d291650bf9a9bdebdcc2