Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package rubygem-rack-2.2 for 
openSUSE:Factory checked in at 2026-04-08 17:17:46
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/rubygem-rack-2.2 (Old)
 and      /work/SRC/openSUSE:Factory/.rubygem-rack-2.2.new.21863 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "rubygem-rack-2.2"

Wed Apr  8 17:17:46 2026 rev:21 rq:1345170 version:2.2.23

Changes:
--------
--- /work/SRC/openSUSE:Factory/rubygem-rack-2.2/rubygem-rack-2.2.changes        
2026-03-04 21:11:50.056833516 +0100
+++ 
/work/SRC/openSUSE:Factory/.rubygem-rack-2.2.new.21863/rubygem-rack-2.2.changes 
    2026-04-08 17:17:56.625382036 +0200
@@ -1,0 +2,15 @@
+Wed Apr  8 11:26:29 UTC 2026 - Saray Cabrera Padron <[email protected]>
+
+- Update to version 2.2.23
+
+  * [CVE-2026-34763] Root directory disclosure via unescaped regex 
interpolation in Rack::Directory.
+  * [CVE-2026-34230] Avoid O(n^2) algorithm in 
Rack::Utils.select_best_encoding which could lead to denial of service.
+  * [CVE-2026-26961] Raise error for multipart requests with multiple boundary 
parameters.
+  * [CVE-2026-34786] Rack::Static header_rules bypass via URL-encoded path 
mismatch.
+  * [CVE-2026-34831] Content-Length mismatch in Rack::Files error responses.
+  * [CVE-2026-34826] Multipart byte range processing allows denial of service 
via excessive overlapping ranges.
+  * [CVE-2026-34830] Rack::Sendfile header-based X-Accel-Mapping regex 
injection enables unauthorized X-Accel-Redirect.
+  * [CVE-2026-34785] Rack::Static prefix matching can expose unintended files 
under the static root.
+  * [CVE-2026-34829] Multipart parsing without Content-Length header allows 
unbounded chunked file uploads. 
+
+-------------------------------------------------------------------

Old:
----
  rack-2.2.22.gem

New:
----
  rack-2.2.23.gem

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ rubygem-rack-2.2.spec ++++++
--- /var/tmp/diff_new_pack.2lJO5y/_old  2026-04-08 17:17:57.509418438 +0200
+++ /var/tmp/diff_new_pack.2lJO5y/_new  2026-04-08 17:17:57.513418602 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package rubygem-rack-2.2
 #
-# Copyright (c) 2025 SUSE LLC and contributors
+# Copyright (c) 2026 SUSE LLC and contributors
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -24,7 +24,7 @@
 #
 
 Name:           rubygem-rack-2.2
-Version:        2.2.22
+Version:        2.2.23
 Release:        0
 %define mod_name rack
 %define mod_full_name %{mod_name}-%{version}
@@ -56,6 +56,7 @@
 
 %install
 %gem_install \
+  --no-rdoc --no-ri \
   --symlink-binaries \
   --doc-files="CHANGELOG.md CONTRIBUTING.md MIT-LICENSE README.rdoc" \
   -f

++++++ rack-2.2.22.gem -> rack-2.2.23.gem ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CHANGELOG.md new/CHANGELOG.md
--- old/CHANGELOG.md    1980-01-02 01:00:00.000000000 +0100
+++ new/CHANGELOG.md    1980-01-02 01:00:00.000000000 +0100
@@ -2,7 +2,21 @@
 
 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/).
 
-## Unreleased
+## [2.2.23] - 2026-04-01
+
+### Security
+
+- [CVE-2026-34763](https://github.com/advisories/GHSA-7mqq-6cf9-v2qp) Root 
directory disclosure via unescaped regex interpolation in `Rack::Directory`.
+- [CVE-2026-34230](https://github.com/advisories/GHSA-v569-hp3g-36wr) Avoid 
O(n^2) algorithm in `Rack::Utils.select_best_encoding` which could lead to 
denial of service.
+- [CVE-2026-26961](https://github.com/advisories/GHSA-vgpv-f759-9wx3) Raise 
error for multipart requests with multiple boundary parameters.
+- [CVE-2026-34786](https://github.com/advisories/GHSA-q4qf-9j86-f5mh) 
`Rack::Static` `header_rules` bypass via URL-encoded path mismatch.
+- [CVE-2026-34831](https://github.com/advisories/GHSA-q2ww-5357-x388) 
`Content-Length` mismatch in `Rack::Files` error responses.
+- [CVE-2026-34826](https://github.com/advisories/GHSA-x8cg-fq8g-mxfx) 
Multipart byte range processing allows denial of service via excessive 
overlapping ranges.
+- [CVE-2026-34830](https://github.com/advisories/GHSA-qv7j-4883-hwh7) 
`Rack::Sendfile` header-based `X-Accel-Mapping` regex injection enables 
unauthorized `X-Accel-Redirect`.
+- [CVE-2026-34785](https://github.com/advisories/GHSA-h2jq-g4cq-5ppq) 
`Rack::Static` prefix matching can expose unintended files under the static 
root.
+- [CVE-2026-34829](https://github.com/advisories/GHSA-8vqr-qjwx-82mw) 
Multipart parsing without `Content-Length` header allows unbounded chunked file 
uploads.
+
+## [2.2.22] - 2026-02-16
 
 ### Security
 
Binary files old/checksums.yaml.gz and new/checksums.yaml.gz differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rack/directory.rb new/lib/rack/directory.rb
--- old/lib/rack/directory.rb   1980-01-02 01:00:00.000000000 +0100
+++ new/lib/rack/directory.rb   1980-01-02 01:00:00.000000000 +0100
@@ -45,7 +45,7 @@
     class DirectoryBody < Struct.new(:root, :path, :files)
       # Yield strings for each part of the directory entry
       def each
-        show_path = Utils.escape_html(path.sub(/^#{root}/, ''))
+        show_path = Utils.escape_html(path.sub(/\A#{Regexp.escape(root)}/, ''))
         yield(DIR_PAGE_HEADER % [ show_path, show_path ])
 
         unless path.chomp('/') == root
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rack/files.rb new/lib/rack/files.rb
--- old/lib/rack/files.rb       1980-01-02 01:00:00.000000000 +0100
+++ new/lib/rack/files.rb       1980-01-02 01:00:00.000000000 +0100
@@ -196,7 +196,7 @@
         status,
         {
           CONTENT_TYPE   => "text/plain",
-          CONTENT_LENGTH => body.size.to_s,
+          CONTENT_LENGTH => body.bytesize.to_s,
           "X-Cascade" => "pass"
         }.merge!(headers),
         [body]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rack/multipart/parser.rb 
new/lib/rack/multipart/parser.rb
--- old/lib/rack/multipart/parser.rb    1980-01-02 01:00:00.000000000 +0100
+++ new/lib/rack/multipart/parser.rb    1980-01-02 01:00:00.000000000 +0100
@@ -41,6 +41,10 @@
       BUFFERED_UPLOAD_BYTESIZE_LIMIT = 
env_int.call("RACK_MULTIPART_BUFFERED_UPLOAD_BYTESIZE_LIMIT", 16 * 1024 * 1024)
       private_constant :BUFFERED_UPLOAD_BYTESIZE_LIMIT
 
+      bytesize_limit = env_int.call("RACK_MULTIPART_PARSER_BYTESIZE_LIMIT", 10 
* 1024 * 1024 * 1024)
+      PARSER_BYTESIZE_LIMIT = bytesize_limit > 0 ? bytesize_limit : nil
+      private_constant :PARSER_BYTESIZE_LIMIT
+
       class BoundedIO # :nodoc:
         def initialize(io, content_length)
           @io             = io
@@ -81,7 +85,15 @@
         return unless content_type
         data = content_type.match(MULTIPART)
         return unless data
-        data[1]
+
+        unless data[1].empty?
+          raise EOFError, "whitespace between boundary parameter name and 
equal sign"
+        end
+        if data.post_match =~ /boundary\s*=/i
+          raise EOFError, "multiple boundary parameters found in multipart 
content type"
+        end
+
+        data[2]
       end
 
       def self.parse(io, content_length, content_type, tmpfile, bufsize, qp)
@@ -90,6 +102,10 @@
         boundary = parse_boundary content_type
         return EMPTY unless boundary
 
+        if PARSER_BYTESIZE_LIMIT && content_length && content_length > 
PARSER_BYTESIZE_LIMIT
+          raise EOFError, "multipart Content-Length #{content_length} exceeds 
limit of #{PARSER_BYTESIZE_LIMIT} bytes"
+        end
+
         io = BoundedIO.new(io, content_length) if content_length
         outbuf = String.new
 
@@ -210,6 +226,7 @@
         @mime_index = 0
         @body_retained = nil
         @retained_size = 0
+        @total_bytes_read = (0 if PARSER_BYTESIZE_LIMIT)
         @collector = Collector.new tempfile
 
         @sbuf = StringScanner.new("".dup)
@@ -221,6 +238,12 @@
 
       def on_read(content)
         handle_empty_content!(content)
+        if @total_bytes_read
+          @total_bytes_read += content.bytesize
+          if @total_bytes_read > PARSER_BYTESIZE_LIMIT
+            raise EOFError, "multipart upload exceeds limit of 
#{PARSER_BYTESIZE_LIMIT} bytes"
+          end
+        end
         @sbuf.concat content
         run_parser
       end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rack/multipart.rb new/lib/rack/multipart.rb
--- old/lib/rack/multipart.rb   1980-01-02 01:00:00.000000000 +0100
+++ new/lib/rack/multipart.rb   1980-01-02 01:00:00.000000000 +0100
@@ -12,7 +12,7 @@
 
     EOL = "\r\n"
     MULTIPART_BOUNDARY = "AaB03x"
-    MULTIPART = %r|\Amultipart/.*boundary=\"?([^\";,]+)\"?|ni
+    MULTIPART = %r|\Amultipart/.*?boundary(\s*)=\"?([^\";,]+)\"?|ni
     TOKEN = /[^\s()<>,;:\\"\/\[\]?=]+/
     CONDISP = /Content-Disposition:\s*#{TOKEN}\s*/i
     VALUE = /"(?:\\"|[^"])*"|#{TOKEN}/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rack/sendfile.rb new/lib/rack/sendfile.rb
--- old/lib/rack/sendfile.rb    1980-01-02 01:00:00.000000000 +0100
+++ new/lib/rack/sendfile.rb    1980-01-02 01:00:00.000000000 +0100
@@ -47,7 +47,7 @@
   #
   # The X-Accel-Mapping header should specify the location on the file system,
   # followed by an equals sign (=), followed name of the private URL pattern
-  # that it maps to. The middleware performs a simple substitution on the
+  # that it maps to. The middleware performs a case-insensitive substitution 
on the
   # resulting path.
   #
   # To enable X-Accel-Redirect, you must configure the middleware explicitly:
@@ -181,7 +181,7 @@
         # Safe to use header: explicit config + no app mappings:
         mapping.split(',').map(&:strip).each do |m|
           internal, external = m.split('=', 2).map(&:strip)
-          new_path = path.sub(/\A#{internal}/i, external)
+          new_path = path.sub(/\A#{Regexp.escape(internal)}/i, external)
           return new_path unless path == new_path
         end
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rack/static.rb new/lib/rack/static.rb
--- old/lib/rack/static.rb      1980-01-02 01:00:00.000000000 +0100
+++ new/lib/rack/static.rb      1980-01-02 01:00:00.000000000 +0100
@@ -91,6 +91,9 @@
     def initialize(app, options = {})
       @app = app
       @urls = options[:urls] || ["/favicon.ico"]
+      if @urls.kind_of?(Array)
+        @urls = @urls.map { |url| [url, url.end_with?('/') ? url : 
"#{url}/".freeze].freeze }.freeze
+      end
       @index = options[:index]
       @gzip = options[:gzip]
       @cascade = options[:cascade]
@@ -113,7 +116,7 @@
     end
 
     def route_file(path)
-      @urls.kind_of?(Array) && @urls.any? { |url| path.index(url) == 0 }
+      @urls.kind_of?(Array) && @urls.any? { |url, url_slash| path == url || 
path.start_with?(url_slash) }
     end
 
     def can_serve(path)
@@ -165,6 +168,8 @@
 
     # Convert HTTP header rules to HTTP headers
     def applicable_rules(path)
+      path = ::Rack::Utils.unescape_path(path)
+
       @header_rules.find_all do |rule, new_headers|
         case rule
         when :all
@@ -172,10 +177,9 @@
         when :fonts
           /\.(?:ttf|otf|eot|woff2|woff|svg)\z/.match?(path)
         when String
-          path = ::Rack::Utils.unescape(path)
           path.start_with?(rule) || path.start_with?('/' + rule)
         when Array
-          /\.(#{rule.join('|')})\z/.match?(path)
+          /\.#{Regexp.union(rule)}\z/.match?(path)
         when Regexp
           rule.match?(path)
         else
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rack/utils.rb new/lib/rack/utils.rb
--- old/lib/rack/utils.rb       1980-01-02 01:00:00.000000000 +0100
+++ new/lib/rack/utils.rb       1980-01-02 01:00:00.000000000 +0100
@@ -186,17 +186,41 @@
       string.to_s.gsub(ESCAPE_HTML_PATTERN){|c| ESCAPE_HTML[c] }
     end
 
+    # Given an array of available encoding strings, and an array of
+    # acceptable encodings for a request, where each element of the
+    # acceptable encodings array is an array where the first element
+    # is an encoding name and the second element is the numeric
+    # priority for the encoding, return the available encoding with
+    # the highest priority.
+    #
+    # The accept_encoding argument is typically generated by calling
+    # Request#accept_encoding.
+    #
+    # Example:
+    #
+    #   select_best_encoding(%w(compress gzip identity),
+    #                        [["compress", 0.5], ["gzip", 1.0]])
+    #   # => "gzip"
+    #
+    # To reduce denial of service potential, only the first 16
+    # acceptable encodings are considered.
     def select_best_encoding(available_encodings, accept_encoding)
       # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
 
+      # Only process the first 16 encodings
+      accept_encoding = accept_encoding[0...16]
       expanded_accept_encoding = []
+      wildcard_seen = false
 
       accept_encoding.each do |m, q|
         preference = available_encodings.index(m) || available_encodings.size
 
         if m == "*"
-          (available_encodings - accept_encoding.map(&:first)).each do |m2|
-            expanded_accept_encoding << [m2, q, preference]
+          unless wildcard_seen
+            (available_encodings - accept_encoding.map(&:first)).each do |m2|
+              expanded_accept_encoding << [m2, q, preference]
+            end
+            wildcard_seen = true
           end
         else
           expanded_accept_encoding << [m, q, preference]
@@ -204,7 +228,13 @@
       end
 
       encoding_candidates = expanded_accept_encoding
-        .sort_by { |_, q, p| [-q, p] }
+        .sort do |(_, q1, p1), (_, q2, p2)|
+          if r = (q1 <=> q2).nonzero?
+            -r
+          else
+            (p1 <=> p2).nonzero? || 0
+          end
+        end
         .map!(&:first)
 
       unless encoding_candidates.include?("identity")
@@ -350,16 +380,17 @@
     # Parses the "Range:" header, if present, into an array of Range objects.
     # Returns nil if the header is missing or syntactically invalid.
     # Returns an empty array if none of the ranges are satisfiable.
-    def byte_ranges(env, size)
-      warn "`byte_ranges` is deprecated, please use `get_byte_ranges`" if 
$VERBOSE
-      get_byte_ranges env['HTTP_RANGE'], size
+    def byte_ranges(env, size, max_ranges: 100)
+      get_byte_ranges env['HTTP_RANGE'], size, max_ranges: max_ranges
     end
 
-    def get_byte_ranges(http_range, size)
+    def get_byte_ranges(http_range, size, max_ranges: 100)
       # See <http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35>
       return nil unless http_range && http_range =~ /bytes=([^;]+)/
+      byte_range = $1
+      return nil if byte_range.count(',') >= max_ranges
       ranges = []
-      $1.split(/,\s*/).each do |range_spec|
+      byte_range.split(/,[ \t]*/).each do |range_spec|
         return nil unless range_spec.include?('-')
         range = range_spec.split('-')
         r0, r1 = range[0], range[1]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/rack/version.rb new/lib/rack/version.rb
--- old/lib/rack/version.rb     1980-01-02 01:00:00.000000000 +0100
+++ new/lib/rack/version.rb     1980-01-02 01:00:00.000000000 +0100
@@ -20,7 +20,7 @@
     VERSION.join(".")
   end
 
-  RELEASE = "2.2.22"
+  RELEASE = "2.2.23"
 
   # Return the Rack release as a dotted string.
   def self.release
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/metadata new/metadata
--- old/metadata        1980-01-02 01:00:00.000000000 +0100
+++ new/metadata        1980-01-02 01:00:00.000000000 +0100
@@ -1,7 +1,7 @@
 --- !ruby/object:Gem::Specification
 name: rack
 version: !ruby/object:Gem::Version
-  version: 2.2.22
+  version: 2.2.23
 platform: ruby
 authors:
 - Leah Neukirchen
@@ -182,7 +182,7 @@
     - !ruby/object:Gem::Version
       version: '0'
 requirements: []
-rubygems_version: 4.0.3
+rubygems_version: 4.0.6
 specification_version: 4
 summary: A modular Ruby webserver interface.
 test_files: []

Reply via email to