puma 5.6.7 → 5.6.9

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: 1f1995d9f43f5297e945ba772d6fa72f814ef2878a6c819ab16774cfab9cf73e
4
- data.tar.gz: f19f67fa86baadcfd6597212ccf50ca1c8dd7879d9920a7a7cf19839a0c4ede4
3
+ metadata.gz: 869ae34fc3a993b7bc996c0053a647afc12fb908e6d5224a841bdafb23974bef
4
+ data.tar.gz: e65a1e6e579b8c8b4d52a77ee9bf4710be1a26f5e4934f96d4502f2b1afa98af
5
5
  SHA512:
6
- metadata.gz: 335b387a7b47b246c3970cbd98556053627e2ef16b00d738a26ac8b67db8847f43b96ebfaddc695ea101a8c9aa9b8189e97b728aaf2596f74e4bbd32d30476f4
7
- data.tar.gz: 02e6d936b3118718c2e9023b8ac512c82ddfed052ccdae9a64965a9d994589ff8f98cdcdad15e6b5c01bbc0bd0cc3ddf203afdb1c7be3ec9c81c26ee2e9479a2
6
+ metadata.gz: b9e1cb266acced0292dc12e0b825344de6cf128a42246625bf166f8042497b75195d354cda77123c5ae8049d062465b58b19395d31cc922e32196072d94ad45c
7
+ data.tar.gz: 522578ae4fc289ff7bd2c71704e7c8b22dcf0bf59db414bc2d5a730243e6daac027d2f4b106e9913f881a53749c75b41fd5c77982b8bfca3768b62f25abde150
data/History.md CHANGED
@@ -1,6 +1,16 @@
1
+ ## 5.6.9 / 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
+ ## 5.6.8 / 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
  ## 5.6.7 / 2023-08-18
2
12
 
3
- * Security
13
+ * Security
4
14
  * Address HTTP request smuggling vulnerabilities with zero-length Content Length header and trailer fields ([GHSA-68xg-gqqm-vgj8](https://github.com/puma/puma/security/advisories/GHSA-68xg-gqqm-vgj8))
5
15
 
6
16
  ## 5.6.6 / 2023-06-21
@@ -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
@@ -48,6 +48,14 @@ module Puma
48
48
  CHUNK_VALID_ENDING = Const::LINE_END
49
49
  CHUNK_VALID_ENDING_SIZE = CHUNK_VALID_ENDING.bytesize
50
50
 
51
+ # The maximum number of bytes we'll buffer looking for a valid
52
+ # chunk header.
53
+ MAX_CHUNK_HEADER_SIZE = 4096
54
+
55
+ # The maximum amount of excess data the client sends
56
+ # using chunk size extensions before we abort the connection.
57
+ MAX_CHUNK_EXCESS = 16 * 1024
58
+
51
59
  # Content-Length header value validation
52
60
  CONTENT_LENGTH_VALUE_INVALID = /[^\d]/.freeze
53
61
 
@@ -460,6 +468,7 @@ module Puma
460
468
  @chunked_body = true
461
469
  @partial_part_left = 0
462
470
  @prev_chunk = ""
471
+ @excess_cr = 0
463
472
 
464
473
  @body = Tempfile.new(Const::PUMA_TMP_BASE)
465
474
  @body.unlink
@@ -541,6 +550,20 @@ module Puma
541
550
  end
542
551
  end
543
552
 
553
+ # Track the excess as a function of the size of the
554
+ # header vs the size of the actual data. Excess can
555
+ # go negative (and is expected to) when the body is
556
+ # significant.
557
+ # The additional of chunk_hex.size and 2 compensates
558
+ # for a client sending 1 byte in a chunked body over
559
+ # a long period of time, making sure that that client
560
+ # isn't accidentally eventually punished.
561
+ @excess_cr += (line.size - len - chunk_hex.size - 2)
562
+
563
+ if @excess_cr >= MAX_CHUNK_EXCESS
564
+ raise HttpParserError, "Maximum chunk excess detected"
565
+ end
566
+
544
567
  len += 2
545
568
 
546
569
  part = io.read(len)
@@ -568,6 +591,10 @@ module Puma
568
591
  @partial_part_left = len - part.size
569
592
  end
570
593
  else
594
+ if @prev_chunk.size + chunk.size >= MAX_CHUNK_HEADER_SIZE
595
+ raise HttpParserError, "maximum size of chunk header exceeded"
596
+ end
597
+
571
598
  @prev_chunk = line
572
599
  return false
573
600
  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 = "5.6.7".freeze
103
+ PUMA_VERSION = VERSION = "5.6.9".freeze
104
104
  CODE_NAME = "Birdie's Version".freeze
105
105
 
106
106
  PUMA_SERVER_STRING = ['puma', PUMA_VERSION, CODE_NAME].join(' ').freeze
@@ -244,6 +244,14 @@ module Puma
244
244
  # header values can contain HTAB?
245
245
  ILLEGAL_HEADER_VALUE_REGEX = /[\x00-\x08\x0A-\x1F]/.freeze
246
246
 
247
+ # The keys of headers that should not be convert to underscore
248
+ # normalized versions. These headers are ignored at the request reading layer,
249
+ # but if we normalize them after reading, it's just confusing for the application.
250
+ UNMASKABLE_HEADERS = {
251
+ "HTTP_TRANSFER,ENCODING" => true,
252
+ "HTTP_CONTENT,LENGTH" => true,
253
+ }
254
+
247
255
  # Banned keys of response header
248
256
  BANNED_HEADER_KEY = /\A(rack\.|status\z)/.freeze
249
257
 
data/lib/puma/null_io.rb CHANGED
File without changes
data/lib/puma/request.rb CHANGED
@@ -318,6 +318,11 @@ module Puma
318
318
  # compatibility, we'll convert them back. This code is written to
319
319
  # avoid allocation in the common case (ie there are no headers
320
320
  # with `,` in their names), that's why it has the extra conditionals.
321
+ #
322
+ # @note If a normalized version of a `,` header already exists, we ignore
323
+ # the `,` version. This prevents clobbering headers managed by proxies
324
+ # but not by clients (Like X-Forwarded-For).
325
+ #
321
326
  # @param env [Hash] see Puma::Client#env, from request, modifies in place
322
327
  # @version 5.0.3
323
328
  #
@@ -326,23 +331,31 @@ module Puma
326
331
  to_add = nil
327
332
 
328
333
  env.each do |k,v|
329
- if k.start_with?("HTTP_") and k.include?(",") and k != "HTTP_TRANSFER,ENCODING"
334
+ if k.start_with?("HTTP_") && k.include?(",") && !UNMASKABLE_HEADERS.key?(k)
330
335
  if to_delete
331
336
  to_delete << k
332
337
  else
333
338
  to_delete = [k]
334
339
  end
335
340
 
341
+ new_k = k.tr(",", "_")
342
+ if env.key?(new_k)
343
+ next
344
+ end
345
+
336
346
  unless to_add
337
347
  to_add = {}
338
348
  end
339
349
 
340
- to_add[k.tr(",", "_")] = v
350
+ to_add[new_k] = v
341
351
  end
342
352
  end
343
353
 
344
- if to_delete
354
+ if to_delete # rubocop:disable Style/SafeNavigation
345
355
  to_delete.each { |k| env.delete(k) }
356
+ end
357
+
358
+ if to_add
346
359
  env.merge! to_add
347
360
  end
348
361
  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: 5.6.7
4
+ version: 5.6.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evan Phoenix
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 1980-01-01 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
@@ -141,7 +141,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
141
141
  - !ruby/object:Gem::Version
142
142
  version: '0'
143
143
  requirements: []
144
- rubygems_version: 3.4.12
144
+ rubygems_version: 3.5.16
145
145
  signing_key:
146
146
  specification_version: 4
147
147
  summary: Puma is a simple, fast, threaded, and highly parallel HTTP 1.1 server for