puma 6.4.1 → 6.4.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1f531bed7745c6a17915748abb3495f7154ee5fb096b4aa251f03651db80966a
4
- data.tar.gz: 718e043e5c9e007c188fc6f172c0e72bb617235b9db176f80706285c5810991a
3
+ metadata.gz: e3cedcd91a2366db019124505992d71ff47717760e4c3f37d9e7ae681c45bbdb
4
+ data.tar.gz: 6ad4999caa3542103c8bb2d3a1bd49202e1c8cf71d409ee96e13d23c169f0d32
5
5
  SHA512:
6
- metadata.gz: 89269a8cb4620dfb35f8cb82cbb0efcbef4b69c5b084ef03b360ee65b1b0e867c4877b2b59841e0221476d45a248a3f38f358a681db5f801a37870d32a07b968
7
- data.tar.gz: d67e3d07fe9cf439c3dc8483ae1625839ea97dbe087800274cd66a76e0eeb26f83173424ce72ad476b9272ab87287f8fd7d525a35e475b2555a92f6f65ebc3f9
6
+ metadata.gz: a69d8cec268d2e35444609f2e69e737e47eb1dc30dd2b3a387e5f3e84bc4905d8241ae3b158f39259a9930ca093fff17db927039aaef54583e6c1a30d8b12a61
7
+ data.tar.gz: f03e924b53e70ac876c786031b23775e4b91aa5d009d5f40fb9a0c241093a238c4b78a99fc062c8495e634b2cfc8561626e9aaf0888c203d40cf84f9d14c539b
data/History.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## 6.4.3 / 2024-09-19
2
+
3
+ * Security
4
+ * Discards any headers using underscores if the non-underscore version also exists. Without this, an attacker could overwrite values set by intermediate proxies (e.g. X-Forwarded-For). ([CVE-2024-45614](https://github.com/puma/puma/security/advisories/GHSA-9hf4-67fc-4vf4)/GHSA-9hf4-67fc-4vf4)
5
+
6
+ ## 6.4.2 / 2024-01-08
7
+
8
+ * Security
9
+ * Limit the size of chunk extensions. Without this limit, an attacker could cause unbounded resource (CPU, network bandwidth) consumption. ([GHSA-c2f4-cvqm-65w2](https://github.com/puma/puma/security/advisories/GHSA-c2f4-cvqm-65w2))
10
+
1
11
  ## 6.4.1 / 2024-01-03
2
12
 
3
13
  * Bugfixes
@@ -168,6 +178,16 @@
168
178
  * Ruby 3.2 will have native IO#wait_* methods, don't require io/wait ([#2903])
169
179
  * Various internal API refactorings ([#2942], [#2921], [#2922], [#2955])
170
180
 
181
+ ## 5.6.9 / 2024-09-19
182
+
183
+ * Security
184
+ * Discards any headers using underscores if the non-underscore version also exists. Without this, an attacker could overwrite values set by intermediate proxies (e.g. X-Forwarded-For). ([CVE-2024-45614](https://github.com/puma/puma/security/advisories/GHSA-9hf4-67fc-4vf4)/GHSA-9hf4-67fc-4vf4)
185
+
186
+ ## 5.6.8 / 2024-01-08
187
+
188
+ * Security
189
+ * Limit the size of chunk extensions. Without this limit, an attacker could cause unbounded resource (CPU, network bandwidth) consumption. ([GHSA-c2f4-cvqm-65w2](https://github.com/puma/puma/security/advisories/GHSA-c2f4-cvqm-65w2))
190
+
171
191
  ## 5.6.7 / 2023-08-18
172
192
 
173
193
  * Security
@@ -99,6 +99,8 @@ public class Http11 extends RubyObject {
99
99
  int bite = b.get(i) & 0xFF;
100
100
  if(bite == '-') {
101
101
  b.set(i, (byte)'_');
102
+ } else if(bite == '_') {
103
+ b.set(i, (byte)',');
102
104
  } else {
103
105
  b.set(i, (byte)Character.toUpperCase(bite));
104
106
  }
data/lib/puma/client.rb CHANGED
@@ -51,6 +51,14 @@ module Puma
51
51
  CHUNK_VALID_ENDING = Const::LINE_END
52
52
  CHUNK_VALID_ENDING_SIZE = CHUNK_VALID_ENDING.bytesize
53
53
 
54
+ # The maximum number of bytes we'll buffer looking for a valid
55
+ # chunk header.
56
+ MAX_CHUNK_HEADER_SIZE = 4096
57
+
58
+ # The maximum amount of excess data the client sends
59
+ # using chunk size extensions before we abort the connection.
60
+ MAX_CHUNK_EXCESS = 16 * 1024
61
+
54
62
  # Content-Length header value validation
55
63
  CONTENT_LENGTH_VALUE_INVALID = /[^\d]/.freeze
56
64
 
@@ -496,6 +504,7 @@ module Puma
496
504
  @chunked_body = true
497
505
  @partial_part_left = 0
498
506
  @prev_chunk = ""
507
+ @excess_cr = 0
499
508
 
500
509
  @body = Tempfile.new(Const::PUMA_TMP_BASE)
501
510
  @body.unlink
@@ -577,6 +586,20 @@ module Puma
577
586
  end
578
587
  end
579
588
 
589
+ # Track the excess as a function of the size of the
590
+ # header vs the size of the actual data. Excess can
591
+ # go negative (and is expected to) when the body is
592
+ # significant.
593
+ # The additional of chunk_hex.size and 2 compensates
594
+ # for a client sending 1 byte in a chunked body over
595
+ # a long period of time, making sure that that client
596
+ # isn't accidentally eventually punished.
597
+ @excess_cr += (line.size - len - chunk_hex.size - 2)
598
+
599
+ if @excess_cr >= MAX_CHUNK_EXCESS
600
+ raise HttpParserError, "Maximum chunk excess detected"
601
+ end
602
+
580
603
  len += 2
581
604
 
582
605
  part = io.read(len)
@@ -604,6 +627,10 @@ module Puma
604
627
  @partial_part_left = len - part.size
605
628
  end
606
629
  else
630
+ if @prev_chunk.size + chunk.size >= MAX_CHUNK_HEADER_SIZE
631
+ raise HttpParserError, "maximum size of chunk header exceeded"
632
+ end
633
+
607
634
  @prev_chunk = line
608
635
  return false
609
636
  end
data/lib/puma/const.rb CHANGED
@@ -100,7 +100,7 @@ module Puma
100
100
  # too taxing on performance.
101
101
  module Const
102
102
 
103
- PUMA_VERSION = VERSION = "6.4.1"
103
+ PUMA_VERSION = VERSION = "6.4.3"
104
104
  CODE_NAME = "The Eagle of Durango"
105
105
 
106
106
  PUMA_SERVER_STRING = ["puma", PUMA_VERSION, CODE_NAME].join(" ").freeze
@@ -281,6 +281,14 @@ module Puma
281
281
  # header values can contain HTAB?
282
282
  ILLEGAL_HEADER_VALUE_REGEX = /[\x00-\x08\x0A-\x1F]/.freeze
283
283
 
284
+ # The keys of headers that should not be convert to underscore
285
+ # normalized versions. These headers are ignored at the request reading layer,
286
+ # but if we normalize them after reading, it's just confusing for the application.
287
+ UNMASKABLE_HEADERS = {
288
+ "HTTP_TRANSFER,ENCODING" => true,
289
+ "HTTP_CONTENT,LENGTH" => true,
290
+ }
291
+
284
292
  # Banned keys of response header
285
293
  BANNED_HEADER_KEY = /\A(rack\.|status\z)/.freeze
286
294
 
data/lib/puma/request.rb CHANGED
@@ -495,6 +495,11 @@ module Puma
495
495
  # compatibility, we'll convert them back. This code is written to
496
496
  # avoid allocation in the common case (ie there are no headers
497
497
  # with `,` in their names), that's why it has the extra conditionals.
498
+ #
499
+ # @note If a normalized version of a `,` header already exists, we ignore
500
+ # the `,` version. This prevents clobbering headers managed by proxies
501
+ # but not by clients (Like X-Forwarded-For).
502
+ #
498
503
  # @param env [Hash] see Puma::Client#env, from request, modifies in place
499
504
  # @version 5.0.3
500
505
  #
@@ -503,23 +508,31 @@ module Puma
503
508
  to_add = nil
504
509
 
505
510
  env.each do |k,v|
506
- if k.start_with?("HTTP_") && k.include?(",") && k != "HTTP_TRANSFER,ENCODING"
511
+ if k.start_with?("HTTP_") && k.include?(",") && !UNMASKABLE_HEADERS.key?(k)
507
512
  if to_delete
508
513
  to_delete << k
509
514
  else
510
515
  to_delete = [k]
511
516
  end
512
517
 
518
+ new_k = k.tr(",", "_")
519
+ if env.key?(new_k)
520
+ next
521
+ end
522
+
513
523
  unless to_add
514
524
  to_add = {}
515
525
  end
516
526
 
517
- to_add[k.tr(",", "_")] = v
527
+ to_add[new_k] = v
518
528
  end
519
529
  end
520
530
 
521
- if to_delete
531
+ if to_delete # rubocop:disable Style/SafeNavigation
522
532
  to_delete.each { |k| env.delete(k) }
533
+ end
534
+
535
+ if to_add
523
536
  env.merge! to_add
524
537
  end
525
538
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: puma
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.4.1
4
+ version: 6.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evan Phoenix
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-01-02 00:00:00.000000000 Z
11
+ date: 2024-09-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nio4r
@@ -145,7 +145,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
145
145
  - !ruby/object:Gem::Version
146
146
  version: '0'
147
147
  requirements: []
148
- rubygems_version: 3.5.3
148
+ rubygems_version: 3.5.16
149
149
  signing_key:
150
150
  specification_version: 4
151
151
  summary: Puma is a simple, fast, threaded, and highly parallel HTTP 1.1 server for