Your message dated Sat, 15 Mar 2025 09:44:44 +0000
with message-id <e1tto4s-005km5...@coccia.debian.org>
and subject line Close 1091795
has caused the Debian Bug report #1091795,
regarding bookworm-pu: package puma/5.6.5-3+deb12u1
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact ow...@bugs.debian.org
immediately.)


-- 
1091795: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1091795
Debian Bug Tracking System
Contact ow...@bugs.debian.org with problems
--- Begin Message ---
Package: release.debian.org
Severity: normal
Tags: bookworm
User: release.debian....@packages.debian.org
Usertags: pu
X-Debbugs-Cc: p...@packages.debian.org
Control: affects -1 + src:puma

Dear stable release team,

[ Reason ]
As a ruby team member I would like to do a update of this package in
stable to fix CVE-2023-40175,CVE-2024-21647 and CVE-2024-45614.

[ Tests ]
All tests from upstream related to this CVE is also backported and ran
successfully along with the existing tests.


[ Checklist ]
  [x] *all* changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in stable
  [x] the issue is verified as fixed in unstable

[ Changes ]
Debdiff are attached.
Except some minor corrections, all changes fitted without any fuzz.
diff -Nru puma-5.6.5/debian/changelog puma-5.6.5/debian/changelog
--- puma-5.6.5/debian/changelog 2023-02-09 20:54:05.000000000 +0530
+++ puma-5.6.5/debian/changelog 2024-12-31 17:44:27.000000000 +0530
@@ -1,3 +1,22 @@
+puma (5.6.5-3+deb12u1) bookworm; urgency=medium
+
+  * Team upload
+  * d/patches/
+   + CVE-2023-40175.patch: Fix CVE-2023-40175, incorrect behavior when
+     parsing chunked transfer encoding bodies and zero-length
+     Content-Length headers in a way that allowed HTTP request
+     smuggling. (Closes: #1050079)
+
+   + CVE-2024-21647.patch: Fix CVE-2024-21647 by limiting the size of
+     chunk extensions. (Closes: #1060345)
+
+   + CVE-2024-45614.patch: Fix CVE-2024-45614, clients could clobber
+     values set by intermediate proxies (such as X-Forwarded-For) by
+     providing a underscore version of the same header.
+     (Closes: #1082379)
+
+ -- Abhijith PA <abhij...@debian.org>  Tue, 31 Dec 2024 17:44:27 +0530
+
 puma (5.6.5-3) unstable; urgency=medium
 
   * Team upload.
diff -Nru puma-5.6.5/debian/patches/CVE-2023-40175.patch 
puma-5.6.5/debian/patches/CVE-2023-40175.patch
--- puma-5.6.5/debian/patches/CVE-2023-40175.patch      1970-01-01 
05:30:00.000000000 +0530
+++ puma-5.6.5/debian/patches/CVE-2023-40175.patch      2024-12-31 
11:04:27.000000000 +0530
@@ -0,0 +1,143 @@
+From 7405a219801dcebc0ad6e0aa108d4319ca23f662 Mon Sep 17 00:00:00 2001
+From: Nate Berkopec <nate.berko...@gmail.com>
+Date: Fri, 18 Aug 2023 09:47:23 +0900
+Subject: [PATCH] Merge pull request from GHSA-68xg-gqqm-vgj8
+
+* Reject empty string for Content-Length
+
+* Ignore trailers in last chunk
+
+* test_puma_server.rb - use heredoc, test_cl_and_te_smuggle
+
+* client.rb - stye/RubyCop
+
+* test_puma_server.rb - indented heredoc rubocop disable
+
+* Dentarg comments
+
+* Remove unused variable
+
+---------
+
+Co-authored-by: MSP-Greg <greg.m...@gmail.com>
+---
+ lib/puma/client.rb       | 23 ++++++++++++++--------
+ test/test_puma_server.rb | 42 +++++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 56 insertions(+), 9 deletions(-)
+
+diff --git a/lib/puma/client.rb b/lib/puma/client.rb
+index e966f995e8..9c11912caa 100644
+--- a/lib/puma/client.rb
++++ b/lib/puma/client.rb
+@@ -45,7 +45,8 @@ class Client
+ 
+     # chunked body validation
+     CHUNK_SIZE_INVALID = /[^\h]/.freeze
+-    CHUNK_VALID_ENDING = "\r\n".freeze
++    CHUNK_VALID_ENDING = Const::LINE_END
++    CHUNK_VALID_ENDING_SIZE = CHUNK_VALID_ENDING.bytesize
+ 
+     # Content-Length header value validation
+     CONTENT_LENGTH_VALUE_INVALID = /[^\d]/.freeze
+@@ -347,8 +348,8 @@ def setup_body
+       cl = @env[CONTENT_LENGTH]
+ 
+       if cl
+-        # cannot contain characters that are not \d
+-        if cl =~ CONTENT_LENGTH_VALUE_INVALID
++        # cannot contain characters that are not \d, or be empty
++        if cl =~ CONTENT_LENGTH_VALUE_INVALID || cl.empty?
+           raise HttpParserError, "Invalid Content-Length: #{cl.inspect}"
+         end
+       else
+@@ -509,7 +510,7 @@ def decode_chunk(chunk)
+ 
+       while !io.eof?
+         line = io.gets
+-        if line.end_with?("\r\n")
++        if line.end_with?(CHUNK_VALID_ENDING)
+           # Puma doesn't process chunk extensions, but should parse if they're
+           # present, which is the reason for the semicolon regex
+           chunk_hex = line.strip[/\A[^;]+/]
+@@ -521,13 +522,19 @@ def decode_chunk(chunk)
+             @in_last_chunk = true
+             @body.rewind
+             rest = io.read
+-            last_crlf_size = "\r\n".bytesize
+-            if rest.bytesize < last_crlf_size
++            if rest.bytesize < CHUNK_VALID_ENDING_SIZE
+               @buffer = nil
+-              @partial_part_left = last_crlf_size - rest.bytesize
++              @partial_part_left = CHUNK_VALID_ENDING_SIZE - rest.bytesize
+               return false
+             else
+-              @buffer = rest[last_crlf_size..-1]
++              # if the next character is a CRLF, set buffer to everything 
after that CRLF
++              start_of_rest = if rest.start_with?(CHUNK_VALID_ENDING)
++                CHUNK_VALID_ENDING_SIZE
++              else # we have started a trailer section, which we do not 
support. skip it!
++                rest.index(CHUNK_VALID_ENDING*2) + CHUNK_VALID_ENDING_SIZE*2
++              end
++
++              @buffer = rest[start_of_rest..-1]
+               @buffer = nil if @buffer.empty?
+               set_ready
+               return true
+diff --git a/test/test_puma_server.rb b/test/test_puma_server.rb
+index 298e44b439..2bfaf98848 100644
+--- a/test/test_puma_server.rb
++++ b/test/test_puma_server.rb
+@@ -627,7 +627,7 @@ def test_large_chunked_request
+       [200, {}, [""]]
+     }
+ 
+-    header = "GET / HTTP/1.1\r\nConnection: close\r\nTransfer-Encoding: 
chunked\r\n\r\n"
++    header = "GET / HTTP/1.1\r\nConnection: close\r\nContent-Length: 
200\r\nTransfer-Encoding: chunked\r\n\r\n"
+ 
+     chunk_header_size = 6 # 4fb8\r\n
+     # Current implementation reads one chunk of CHUNK_SIZE, then more chunks 
of size 4096.
+@@ -1365,4 +1365,44 @@ def test_rack_url_scheme_user
+     data = send_http_and_read "GET / HTTP/1.0\r\n\r\n"
+     assert_equal "user", data.split("\r\n").last
+   end
++
++  def test_cl_empty_string
++    server_run do |env|
++      [200, {}, [""]]
++    end
++
++    empty_cl_request = "GET / HTTP/1.1\r\nHost: 
localhost\r\nContent-Length:\r\n\r\nGET / HTTP/1.1\r\nHost: localhost\r\n\r\n"
++
++    data = send_http_and_read empty_cl_request
++    assert_operator data, :start_with?, 'HTTP/1.1 400 Bad Request'
++  end
++
++  def test_crlf_trailer_smuggle
++    server_run do |env|
++      [200, {}, [""]]
++    end
++
++    smuggled_payload = "GET / HTTP/1.1\r\nTransfer-Encoding: chunked\r\nHost: 
whatever\r\n\r\n0\r\nX:POST / HTTP/1.1\r\nHost: whatever\r\n\r\nGET / 
HTTP/1.1\r\nHost: whatever\r\n\r\n"
++
++    data = send_http_and_read smuggled_payload
++    assert_equal 2, data.scan("HTTP/1.1 200 OK").size
++  end
++
++  # test to check if content-length is ignored when 'transfer-encoding: 
chunked'
++  # is used.  See also test_large_chunked_request
++  def test_cl_and_te_smuggle
++    body = nil
++    server_run { |env|
++      body = env['rack.input'].read
++      [200, {}, [""]]
++    }
++
++    req = "POST /search HTTP/1.1\r\nHost: 
vulnerable-website.com\r\nContent-Type: 
application/x-www-form-urlencoded\r\nContent-Length: 4\r\nTransfer-Encoding: 
chunked\r\n\r\n7b\r\nGET /404 HTTP/1.1\r\nHost: 
vulnerable-website.com\r\nContent-Type: 
application/x-www-form-urlencoded\r\nContent-Length: 144\r\n\r\nx=\r\n0\r\n\r\n"
++
++    data = send_http_and_read req
++
++    assert_includes body, "GET /404 HTTP/1.1\r\n"
++    assert_includes body, "Content-Length: 144\r\n"
++    assert_equal 1, data.scan("HTTP/1.1 200 OK").size
++  end
+ end
diff -Nru puma-5.6.5/debian/patches/CVE-2024-21647.patch 
puma-5.6.5/debian/patches/CVE-2024-21647.patch
--- puma-5.6.5/debian/patches/CVE-2024-21647.patch      1970-01-01 
05:30:00.000000000 +0530
+++ puma-5.6.5/debian/patches/CVE-2024-21647.patch      2024-12-31 
11:37:42.000000000 +0530
@@ -0,0 +1,93 @@
+From bbb880ffb6debbfdea535b4b3eb2204d49ae151d Mon Sep 17 00:00:00 2001
+From: Nate Berkopec <nate.berko...@gmail.com>
+Date: Mon, 8 Jan 2024 14:48:43 +0900
+Subject: [PATCH] Merge pull request from GHSA-c2f4-cvqm-65w2
+
+Co-authored-by: MSP-Greg <msp-g...@users.noreply.github.com>
+Co-authored-by: Patrik Ragnarsson <pat...@starkast.net>
+Co-authored-by: Evan Phoenix <e...@phx.io>
+---
+ lib/puma/client.rb       | 27 +++++++++++++++++++++++++++
+ test/test_puma_server.rb | 14 ++++++++++++++
+ 2 files changed, 41 insertions(+)
+
+--- a/lib/puma/client.rb
++++ b/lib/puma/client.rb
+@@ -48,6 +48,14 @@ module Puma
+     CHUNK_VALID_ENDING = Const::LINE_END
+     CHUNK_VALID_ENDING_SIZE = CHUNK_VALID_ENDING.bytesize
+ 
++    # The maximum number of bytes we'll buffer looking for a valid
++    # chunk header.
++    MAX_CHUNK_HEADER_SIZE = 4096
++
++    # The maximum amount of excess data the client sends
++    # using chunk size extensions before we abort the connection.
++    MAX_CHUNK_EXCESS = 16 * 1024
++
+     # Content-Length header value validation
+     CONTENT_LENGTH_VALUE_INVALID = /[^\d]/.freeze
+ 
+@@ -460,6 +468,7 @@ module Puma
+       @chunked_body = true
+       @partial_part_left = 0
+       @prev_chunk = ""
++      @excess_cr = 0
+ 
+       @body = Tempfile.new(Const::PUMA_TMP_BASE)
+       @body.unlink
+@@ -541,6 +550,20 @@ module Puma
+             end
+           end
+ 
++          # Track the excess as a function of the size of the
++          # header vs the size of the actual data. Excess can
++          # go negative (and is expected to) when the body is
++          # significant.
++          # The additional of chunk_hex.size and 2 compensates
++          # for a client sending 1 byte in a chunked body over
++          # a long period of time, making sure that that client
++          # isn't accidentally eventually punished.
++          @excess_cr += (line.size - len - chunk_hex.size - 2)
++
++          if @excess_cr >= MAX_CHUNK_EXCESS
++            raise HttpParserError, "Maximum chunk excess detected"
++          end
++
+           len += 2
+ 
+           part = io.read(len)
+@@ -568,6 +591,10 @@ module Puma
+             @partial_part_left = len - part.size
+           end
+         else
++          if @prev_chunk.size + chunk.size >= MAX_CHUNK_HEADER_SIZE
++            raise HttpParserError, "maximum size of chunk header exceeded"
++          end
++
+           @prev_chunk = line
+           return false
+         end
+--- a/test/test_puma_server.rb
++++ b/test/test_puma_server.rb
+@@ -648,6 +648,20 @@ EOF
+     end
+   end
+ 
++  def test_large_chunked_request_header
++    server_run(environment: :production) { |env|
++      [200, {}, [""]]
++    }
++
++    max_chunk_header_size = Puma::Client::MAX_CHUNK_HEADER_SIZE
++    header = "GET / HTTP/1.1\r\nConnection: close\r\nContent-Length: 
200\r\nTransfer-Encoding: chunked\r\n\r\n"
++    socket = send_http "#{header}1;t#{'x' * (max_chunk_header_size + 2)}"
++
++    data = socket.read
++
++    assert_match "HTTP/1.1 400 Bad Request\r\n\r\n", data
++  end
++
+   def test_chunked_request_pause_before_value
+     body = nil
+     content_length = nil
diff -Nru puma-5.6.5/debian/patches/CVE-2024-45614.patch 
puma-5.6.5/debian/patches/CVE-2024-45614.patch
--- puma-5.6.5/debian/patches/CVE-2024-45614.patch      1970-01-01 
05:30:00.000000000 +0530
+++ puma-5.6.5/debian/patches/CVE-2024-45614.patch      2024-12-31 
14:00:04.000000000 +0530
@@ -0,0 +1,195 @@
+From cac3fd18cf29ed43719ff5d52d9cfec215f0a043 Mon Sep 17 00:00:00 2001
+From: Evan Phoenix <e...@phx.io>
+Date: Wed, 18 Sep 2024 21:56:07 -0700
+Subject: [PATCH] Merge commit from fork
+
+* Prevent underscores from clobbering hyphen headers
+
+* Special case encoding headers to prevent app confusion
+
+* Handle _ as , in jruby as well
+
+* Silence RuboCop offense
+
+---------
+
+Co-authored-by: Patrik Ragnarsson <pat...@starkast.net>
+---
+ ext/puma_http11/org/jruby/puma/Http11.java |  2 +
+ lib/puma/const.rb                          |  8 +++
+ lib/puma/request.rb                        | 19 ++++++--
+ test/test_normalize.rb                     | 57 ++++++++++++++++++++++
+ test/test_request_invalid.rb               | 28 +++++++++++
+ 5 files changed, 111 insertions(+), 3 deletions(-)
+ create mode 100644 test/test_normalize.rb
+
+--- a/ext/puma_http11/org/jruby/puma/Http11.java
++++ b/ext/puma_http11/org/jruby/puma/Http11.java
+@@ -99,6 +99,8 @@ public class Http11 extends RubyObject {
+             int bite = b.get(i) & 0xFF;
+             if(bite == '-') {
+                 b.set(i, (byte)'_');
++            } else if(bite == '_') {
++                b.set(i, (byte)',');
+             } else {
+                 b.set(i, (byte)Character.toUpperCase(bite));
+             }
+--- a/lib/puma/const.rb
++++ b/lib/puma/const.rb
+@@ -244,6 +244,14 @@ module Puma
+     # header values can contain HTAB?
+     ILLEGAL_HEADER_VALUE_REGEX = /[\x00-\x08\x0A-\x1F]/.freeze
+ 
++    # The keys of headers that should not be convert to underscore
++    # normalized versions. These headers are ignored at the request reading 
layer,
++    # but if we normalize them after reading, it's just confusing for the 
application.
++    UNMASKABLE_HEADERS = {
++      "HTTP_TRANSFER,ENCODING" => true,
++      "HTTP_CONTENT,LENGTH" => true,
++    }
++
+     # Banned keys of response header
+     BANNED_HEADER_KEY = /\A(rack\.|status\z)/.freeze
+ 
+--- a/lib/puma/request.rb
++++ b/lib/puma/request.rb
+@@ -318,6 +318,11 @@ module Puma
+     # compatibility, we'll convert them back. This code is written to
+     # avoid allocation in the common case (ie there are no headers
+     # with `,` in their names), that's why it has the extra conditionals.
++    #
++    # @note If a normalized version of a `,` header already exists, we ignore
++    #       the `,` version. This prevents clobbering headers managed by 
proxies
++    #       but not by clients (Like X-Forwarded-For).
++    #
+     # @param env [Hash] see Puma::Client#env, from request, modifies in place
+     # @version 5.0.3
+     #
+@@ -326,23 +331,30 @@ module Puma
+       to_add = nil
+ 
+       env.each do |k,v|
+-        if k.start_with?("HTTP_") and k.include?(",") and k != 
"HTTP_TRANSFER,ENCODING"
++        if k.start_with?("HTTP_") and k.include?(",") and 
!UNMASKABLE_HEADERS.key?(k)
+           if to_delete
+             to_delete << k
+           else
+             to_delete = [k]
+           end
+ 
++          new_k = k.tr(",", "_")
++          if env.key?(new_k)
++            next
++          end
++
+           unless to_add
+             to_add = {}
+           end
+ 
+-          to_add[k.tr(",", "_")] = v
++          to_add[new_k] = v
+         end
+       end
+ 
+       if to_delete
+         to_delete.each { |k| env.delete(k) }
++      end
++      if to_add
+         env.merge! to_add
+       end
+     end
+--- /dev/null
++++ b/test/test_normalize.rb
+@@ -0,0 +1,57 @@
++# frozen_string_literal: true
++
++require_relative "helper"
++
++require "puma/request"
++
++class TestNormalize < Minitest::Test
++  parallelize_me!
++
++  include Puma::Request
++
++  def test_comma_headers
++    env = {
++      "HTTP_X_FORWARDED_FOR" => "1.1.1.1",
++      "HTTP_X_FORWARDED,FOR" => "2.2.2.2",
++    }
++
++    req_env_post_parse env
++
++    expected = {
++      "HTTP_X_FORWARDED_FOR" => "1.1.1.1",
++    }
++
++    assert_equal expected, env
++
++    # Test that the iteration order doesn't matter
++
++    env = {
++      "HTTP_X_FORWARDED,FOR" => "2.2.2.2",
++      "HTTP_X_FORWARDED_FOR" => "1.1.1.1",
++    }
++
++    req_env_post_parse env
++
++    expected = {
++      "HTTP_X_FORWARDED_FOR" => "1.1.1.1",
++    }
++
++    assert_equal expected, env
++  end
++
++  def test_unmaskable_headers
++    env = {
++      "HTTP_CONTENT,LENGTH" => "100000",
++      "HTTP_TRANSFER,ENCODING" => "chunky"
++    }
++
++    req_env_post_parse env
++
++    expected = {
++      "HTTP_CONTENT,LENGTH" => "100000",
++      "HTTP_TRANSFER,ENCODING" => "chunky"
++    }
++
++    assert_equal expected, env
++  end
++end
+--- a/test/test_request_invalid.rb
++++ b/test/test_request_invalid.rb
+@@ -216,4 +216,32 @@ class TestRequestInvalid < Minitest::Tes
+ 
+     assert_status data
+   end
++
++  def test_underscore_header_1
++    hdrs = [
++      "X-FORWARDED-FOR: 1.1.1.1",  # proper
++      "X-FORWARDED-FOR: 2.2.2.2",  # proper
++      "X_FORWARDED-FOR: 3.3.3.3",  # invalid, contains underscore
++      "Content-Length: 5",
++    ].join "\r\n"
++
++    response = send_http_and_read "#{GET_PREFIX}#{hdrs}\r\n\r\nHello\r\n\r\n"
++
++    assert_includes response, "HTTP_X_FORWARDED_FOR = 1.1.1.1, 2.2.2.2"
++    refute_includes response, "3.3.3.3"
++  end
++
++  def test_underscore_header_2
++    hdrs = [
++      "X_FORWARDED-FOR: 3.3.3.3",  # invalid, contains underscore
++      "X-FORWARDED-FOR: 2.2.2.2",  # proper
++      "X-FORWARDED-FOR: 1.1.1.1",  # proper
++      "Content-Length: 5",
++    ].join "\r\n"
++
++    response = send_http_and_read "#{GET_PREFIX}#{hdrs}\r\n\r\nHello\r\n\r\n"
++
++    assert_includes response, "HTTP_X_FORWARDED_FOR = 2.2.2.2, 1.1.1.1"
++    refute_includes response, "3.3.3.3"
++  end
+ end
diff -Nru puma-5.6.5/debian/patches/series puma-5.6.5/debian/patches/series
--- puma-5.6.5/debian/patches/series    2023-02-09 20:54:05.000000000 +0530
+++ puma-5.6.5/debian/patches/series    2024-12-31 11:54:18.000000000 +0530
@@ -3,3 +3,6 @@
 0012-disable-cli-ssl-tests.patch
 0013-fix-test-term-not-accepts-new-connections.patch
 0014-disable-test-failing-on-amd64.patch
+CVE-2023-40175.patch
+CVE-2024-21647.patch
+CVE-2024-45614.patch

--- End Message ---
--- Begin Message ---
Version: 12.10
This update has been released as part of 12.10. Thank you for your contribution.

--- End Message ---

Reply via email to