import UBI ruby-2.5.9-115.module+el8.10.0+24408+7ffaaa88
This commit is contained in:
parent
b4a187f265
commit
6bc5e278e1
@ -0,0 +1,332 @@
|
||||
From ac248b06de768b68120b910b2977d55320871b0e Mon Sep 17 00:00:00 2001
|
||||
From: nick evans <nick@rubinick.dev>
|
||||
Date: Sun, 29 Mar 2026 12:26:48 -0400
|
||||
Subject: [PATCH 1/5] =?UTF-8?q?=F0=9F=8D=92=20pick=20257ede0df:=20?=
|
||||
=?UTF-8?q?=F0=9F=A5=85=20Re-raise=20`#starttls`=20error=20from=20receiver?=
|
||||
=?UTF-8?q?=20thread=20[backports=20#395]?=
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Backports #395 to `v0.3-stable`. The tests required an additional
|
||||
rescue-and-ignore for the server thread in `starttls_test`, which was
|
||||
already present in all later branches.
|
||||
|
||||
---------
|
||||
|
||||
When `start_tls_session` raises an exception, that's caught in the
|
||||
receiver thread, but not re-raised. Fortunately, `@sock` will now be
|
||||
a permanently broken SSLSocket, so I don't think this can lead to
|
||||
accidentally using an insecure connection.
|
||||
|
||||
Even so, `#starttls` should disconnect the socket and re-raise the error
|
||||
immediately.
|
||||
|
||||
Failing test case was provided by @rhenium in #394.
|
||||
|
||||
Co-authored-by: Kazuki Yamaguchi <k@rhe.jp>
|
||||
---
|
||||
lib/net/imap.rb | 10 +++++++++-
|
||||
test/net/imap/test_imap.rb | 15 +++++++++++++++
|
||||
2 files changed, 24 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/lib/net/imap.rb b/lib/net/imap.rb
|
||||
index eedcb4f5cf..7a3cd68e81 100644
|
||||
--- a/lib/net/imap.rb
|
||||
+++ b/lib/net/imap.rb
|
||||
@@ -376,7 +376,8 @@ def logout
|
||||
|
||||
# Sends a STARTTLS command to start TLS session.
|
||||
def starttls(options = {}, verify = true)
|
||||
- send_command("STARTTLS") do |resp|
|
||||
+ error = nil
|
||||
+ ok = send_command("STARTTLS") do |resp|
|
||||
if resp.kind_of?(TaggedResponse) && resp.name == "OK"
|
||||
begin
|
||||
# for backward compatibility
|
||||
@@ -386,7 +387,14 @@ def starttls(options = {}, verify = true)
|
||||
end
|
||||
start_tls_session(options)
|
||||
end
|
||||
+ rescue Exception => error
|
||||
+ raise # note that the error backtrace is in the receiver_thread
|
||||
end
|
||||
+ if error
|
||||
+ disconnect
|
||||
+ raise error
|
||||
+ end
|
||||
+ ok
|
||||
end
|
||||
|
||||
# Sends an AUTHENTICATE command to authenticate the client.
|
||||
diff --git a/test/net/imap/test_imap.rb b/test/net/imap/test_imap.rb
|
||||
index 2a9447c0e1..b35b3ff52e 100644
|
||||
--- a/test/net/imap/test_imap.rb
|
||||
+++ b/test/net/imap/test_imap.rb
|
||||
@@ -113,6 +113,20 @@ def test_imaps_post_connection_check
|
||||
end
|
||||
|
||||
if defined?(OpenSSL::SSL)
|
||||
+ def test_starttls_unknown_ca
|
||||
+ imap = nil
|
||||
+ ex = nil
|
||||
+ starttls_test do |port|
|
||||
+ imap = Net::IMAP.new("localhost", port: port)
|
||||
+ begin
|
||||
+ imap.starttls
|
||||
+ rescue => ex
|
||||
+ end
|
||||
+ imap
|
||||
+ end
|
||||
+ assert_kind_of(OpenSSL::SSL::SSLError, ex)
|
||||
+ end
|
||||
+
|
||||
def test_starttls
|
||||
imap = nil
|
||||
starttls_test do |port|
|
||||
@@ -765,6 +779,7 @@ def starttls_test
|
||||
sock.gets
|
||||
sock.print("* BYE terminating connection\r\n")
|
||||
sock.print("RUBY0002 OK LOGOUT completed\r\n")
|
||||
+ rescue OpenSSL::SSL::SSLError
|
||||
ensure
|
||||
sock.close
|
||||
server.close
|
||||
|
||||
From 28d2087a097aab75b2d41fddc6dd457a94f657a2 Mon Sep 17 00:00:00 2001
|
||||
From: nick evans <nicholas.evans@gmail.com>
|
||||
Date: Tue, 14 Feb 2023 00:13:11 -0500
|
||||
Subject: [PATCH 2/5] =?UTF-8?q?=F0=9F=8D=92=20pick=20609acd9fa:=20?=
|
||||
=?UTF-8?q?=F0=9F=A5=85=20Add=20new=20`InvalidResponseError`=20exception?=
|
||||
=?UTF-8?q?=20class=20[backport=20#198]?=
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This copies the InvalidResponseError from #198 and the rdoc update to
|
||||
UnknownResponseError. The behavioral changes from that PR have _not_
|
||||
been copied.
|
||||
|
||||
===
|
||||
|
||||
The UnknownResponseError is brought into Ruby 2.5 by
|
||||
ruby-2.6.8-net-imap-startls-stripping-vulnerability.patch,
|
||||
The errors.rb file does not exist for net-imap on Ruby 2.5, so move the
|
||||
InvalidResponseError into approximately similar location to be used by
|
||||
follow-up commits.
|
||||
---
|
||||
lib/net/imap.rb | 20 ++++++++++++++++++++
|
||||
1 file changed, 20 insertions(+)
|
||||
|
||||
diff --git a/lib/net/imap.rb b/lib/net/imap.rb
|
||||
index 7a3cd68e81..fee094c46d 100644
|
||||
--- a/lib/net/imap.rb
|
||||
+++ b/lib/net/imap.rb
|
||||
@@ -3724,7 +3724,27 @@ class BadResponseError < ResponseError
|
||||
class ByeResponseError < ResponseError
|
||||
end
|
||||
|
||||
+ # Error raised when the server sends an invalid response.
|
||||
+ #
|
||||
+ # This is different from UnknownResponseError: the response has been
|
||||
+ # rejected. Although it may be parsable, the server is forbidden from
|
||||
+ # sending it in the current context. The client should automatically
|
||||
+ # disconnect, abruptly (without logout).
|
||||
+ #
|
||||
+ # Note that InvalidResponseError does not inherit from ResponseError: it
|
||||
+ # can be raised before the response is fully parsed. A related
|
||||
+ # ResponseParseError or ResponseError may be the #cause.
|
||||
+ class InvalidResponseError < Error
|
||||
+ end
|
||||
+
|
||||
# Error raised upon an unknown response from the server.
|
||||
+ #
|
||||
+ # This is different from InvalidResponseError: the response may be a
|
||||
+ # valid extension response and the server may be allowed to send it in
|
||||
+ # this context, but Net::IMAP either does not know how to parse it or
|
||||
+ # how to handle it. This could result from enabling unknown or
|
||||
+ # unhandled extensions. The connection may still be usable,
|
||||
+ # but—depending on context—it may be prudent to disconnect.
|
||||
class UnknownResponseError < ResponseError
|
||||
end
|
||||
|
||||
|
||||
From 9f4030066f7ede86b986ef87ed1610f242edc4ca Mon Sep 17 00:00:00 2001
|
||||
From: nick evans <nick@rubinick.dev>
|
||||
Date: Fri, 27 Mar 2026 17:16:25 -0400
|
||||
Subject: [PATCH 3/5] =?UTF-8?q?=F0=9F=8D=92=20pick=2046636cae8:=20?=
|
||||
=?UTF-8?q?=E2=9D=8C=F0=9F=94=92=20Add=20failing=20test=20for=20STARTTLS?=
|
||||
=?UTF-8?q?=20stripping=20[backport=20#664]?=
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
I'm putting this in its own commit to simplify testing across backports.
|
||||
Also, I'm taking a "belt-and-suspenders" approach, and I'm going to test
|
||||
that either of the two fixes passes the tests.
|
||||
---
|
||||
test/net/imap/test_imap.rb | 34 ++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 34 insertions(+)
|
||||
|
||||
diff --git a/test/net/imap/test_imap.rb b/test/net/imap/test_imap.rb
|
||||
index b35b3ff52e..33606f400b 100644
|
||||
--- a/test/net/imap/test_imap.rb
|
||||
+++ b/test/net/imap/test_imap.rb
|
||||
@@ -151,6 +151,40 @@ def test_starttls_stripping
|
||||
imap
|
||||
end
|
||||
end
|
||||
+
|
||||
+ def test_starttls_stripping_ok_sent_before_response
|
||||
+ # to coordinate between threads (better than sleep)
|
||||
+ server_to_client, client_to_server = Queue.new, Queue.new
|
||||
+ imap = nil
|
||||
+ server = create_tcp_server
|
||||
+ port = server.addr[1]
|
||||
+ start_server do
|
||||
+ sock = server.accept
|
||||
+ begin
|
||||
+ sock.print("* OK test server\r\n")
|
||||
+ assert_equal :send_malicious_response, client_to_server.pop
|
||||
+ sock.print("RUBY0001 OK hahaha, fooled you!\r\n")
|
||||
+ server_to_client << :malicious_response_sent
|
||||
+ sock.gets
|
||||
+ ensure
|
||||
+ sock.close
|
||||
+ server.close
|
||||
+ end
|
||||
+ end
|
||||
+ begin
|
||||
+ imap = Net::IMAP.new("localhost", :port => port)
|
||||
+ client_to_server << :send_malicious_response
|
||||
+ assert_equal :malicious_response_sent, server_to_client.pop
|
||||
+ sleep 0.010 # to be sure the network buffers have flushed, etc
|
||||
+ assert_raise(Net::IMAP::InvalidResponseError) do
|
||||
+ imap.starttls(:ca_file => CA_FILE)
|
||||
+ end
|
||||
+ assert imap.disconnected?
|
||||
+ ensure
|
||||
+ imap.disconnect if imap && !imap.disconnected?
|
||||
+ end
|
||||
+ assert imap.disconnected?
|
||||
+ end
|
||||
end
|
||||
|
||||
def start_server
|
||||
|
||||
From eff739307c73c371769769ca183a0e66baac1e2b Mon Sep 17 00:00:00 2001
|
||||
From: nick evans <nick@rubinick.dev>
|
||||
Date: Fri, 27 Mar 2026 17:31:11 -0400
|
||||
Subject: [PATCH 4/5] =?UTF-8?q?=F0=9F=8D=92=20pick=2062eea6ffe:=20?=
|
||||
=?UTF-8?q?=F0=9F=94=92=F0=9F=A5=85=20Ensure=20STARTTLS=20tagged=20respons?=
|
||||
=?UTF-8?q?e=20was=20handled=20[backport=20#664]?=
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Taking a "belt-and-suspenders" approach to a STARTTLS stripping attack:
|
||||
|
||||
This handles `STARTTLS` as a special-case: if the `STARTTLS` handler
|
||||
did not run, for _whatever_ reason, an exception _must_ be raised and
|
||||
the connection dropped.
|
||||
|
||||
_No_ command should ever receive a tagged `OK` prior to completely
|
||||
sending the command. But `STARTTLS` is security-sensitive enough to
|
||||
warrant this special-case handler.
|
||||
---
|
||||
lib/net/imap.rb | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
diff --git a/lib/net/imap.rb b/lib/net/imap.rb
|
||||
index fee094c46d..e57f96a464 100644
|
||||
--- a/lib/net/imap.rb
|
||||
+++ b/lib/net/imap.rb
|
||||
@@ -376,9 +376,11 @@ def logout
|
||||
|
||||
# Sends a STARTTLS command to start TLS session.
|
||||
def starttls(options = {}, verify = true)
|
||||
+ handled = false
|
||||
error = nil
|
||||
ok = send_command("STARTTLS") do |resp|
|
||||
if resp.kind_of?(TaggedResponse) && resp.name == "OK"
|
||||
+ handled = true
|
||||
begin
|
||||
# for backward compatibility
|
||||
certs = options.to_str
|
||||
@@ -394,6 +396,13 @@ def starttls(options = {}, verify = true)
|
||||
disconnect
|
||||
raise error
|
||||
end
|
||||
+ unless handled
|
||||
+ disconnect
|
||||
+ raise InvalidResponseError,
|
||||
+ "STARTTLS handler was bypassed, although server responded %p" % [
|
||||
+ ok.raw_data.chomp
|
||||
+ ]
|
||||
+ end
|
||||
ok
|
||||
end
|
||||
|
||||
|
||||
From 2cbdd94ad824721797a17436f60027fb781e8bac Mon Sep 17 00:00:00 2001
|
||||
From: nick evans <nick@rubinick.dev>
|
||||
Date: Fri, 27 Mar 2026 18:00:09 -0400
|
||||
Subject: [PATCH 5/5] =?UTF-8?q?=F0=9F=8D=92=20pick=2024d5c773d:=20?=
|
||||
=?UTF-8?q?=F0=9F=94=92=F0=9F=A5=85=20Handle=20tagged=20"OK"=20to=20incomp?=
|
||||
=?UTF-8?q?lete=20command=20[backport=20#664]?=
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Taking a "belt-and-suspenders" approach:
|
||||
|
||||
This is a potential problem for any command which registers a response
|
||||
handler: a malicious server can easily guess what the next tag will be,
|
||||
and send an `OK` response _before_ the client the response handler is
|
||||
attached.
|
||||
|
||||
`STARTTLS` is an extreme example of this issue: if the `STARTTLS`
|
||||
handler does not run, then `#starttls` will not start the TLS session,
|
||||
and the connection is not secured, _but no error is raised._
|
||||
|
||||
We should _also_ attach the response handler before sending the `CRLF`,
|
||||
but that is neither necessary (the response handler will added before
|
||||
the `synchronize` mutex is unlocked) nor sufficient (the fake `OK` can
|
||||
be sent _much_ earlier).
|
||||
|
||||
On the other hand, it _is_ okay for the server to send an error tagged
|
||||
response (`NO` or `BAD`), before the sending the command has completed.
|
||||
---
|
||||
lib/net/imap.rb | 12 ++++++++++++
|
||||
1 file changed, 12 insertions(+)
|
||||
|
||||
diff --git a/lib/net/imap.rb b/lib/net/imap.rb
|
||||
index e57f96a464..692d6e297a 100644
|
||||
--- a/lib/net/imap.rb
|
||||
+++ b/lib/net/imap.rb
|
||||
@@ -1279,6 +1279,7 @@ def send_command(cmd, *args, &block)
|
||||
put_string(" ")
|
||||
send_data(i, tag)
|
||||
end
|
||||
+ guard_against_tagged_response_skipping_handler!(tag)
|
||||
put_string(CRLF)
|
||||
if cmd == "LOGOUT"
|
||||
@logout_command_tag = tag
|
||||
@@ -1294,6 +1295,17 @@ def send_command(cmd, *args, &block)
|
||||
end
|
||||
end
|
||||
end
|
||||
+ rescue InvalidResponseError
|
||||
+ disconnect
|
||||
+ raise
|
||||
+ end
|
||||
+
|
||||
+ def guard_against_tagged_response_skipping_handler!(tag)
|
||||
+ return unless (resp = @tagged_responses[tag])&.name&.upcase == "OK"
|
||||
+ raise(InvalidResponseError,
|
||||
+ "Server sent tagged 'OK' before command was finished: %p. " \
|
||||
+ "This could indicate a malicious server or client-side " \
|
||||
+ "command injection. Disconnecting." % [resp.raw_data.chomp])
|
||||
end
|
||||
|
||||
def generate_tag
|
||||
@ -0,0 +1,242 @@
|
||||
From 20814a27978725dfcbce7f1b149d4cb44e634653 Mon Sep 17 00:00:00 2001
|
||||
From: nick evans <nick@rubinick.dev>
|
||||
Date: Wed, 22 Apr 2026 11:25:06 -0400
|
||||
Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=8D=92=20edit=20ca72ac45:=20=E2=99=BB?=
|
||||
=?UTF-8?q?=EF=B8=8F=20Extract=20superclass=20for=20(internal)=20command?=
|
||||
=?UTF-8?q?=20data?=
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Unlike the cherry-picked commit (ca72ac45), this _only_ makes
|
||||
`CommandData` the superclass for `Literal` and `Atom`. Because those
|
||||
are the classes that will be modified by later cherry-picked commits.
|
||||
This allows those other commits to merge more cleanly, and work with
|
||||
fewer modifications.
|
||||
---
|
||||
lib/net/imap.rb | 44 ++++++++++++++++++++++++++++----------------
|
||||
1 file changed, 28 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/lib/net/imap.rb b/lib/net/imap.rb
|
||||
index 692d6e297a..ba44d21956 100644
|
||||
--- a/lib/net/imap.rb
|
||||
+++ b/lib/net/imap.rb
|
||||
@@ -1566,22 +1566,43 @@ def start_tls_session(params = {})
|
||||
end
|
||||
end
|
||||
|
||||
- class RawData # :nodoc:
|
||||
+ # simplistic emulation of CommandData = Data.define(:data)
|
||||
+ class CommandData
|
||||
+ class << self
|
||||
+ def new(arg = nil, data: arg) super(data: data) end
|
||||
+ alias :[] :new
|
||||
+ end
|
||||
+
|
||||
+ def initialize(data:)
|
||||
+ @data = data
|
||||
+ freeze
|
||||
+ end
|
||||
+
|
||||
+ attr_reader :data
|
||||
+
|
||||
+ def to_h(&block) block ? to_h.to_h(&block) : { data: data } end
|
||||
+ def ==(other) self.class === other && to_h == other.to_h end
|
||||
+ def eql?(other) self.class === other && to_h.eql?(other.to_h) end
|
||||
+
|
||||
+ # following class definition goes beyond the basic Data.define(:data)
|
||||
+ ##
|
||||
+
|
||||
def send_data(imap, tag)
|
||||
- imap.send(:put_string, @data)
|
||||
+ raise NoMethodError, "#{self.class} must implement #{__method__}"
|
||||
end
|
||||
|
||||
def validate
|
||||
end
|
||||
+ end
|
||||
|
||||
- private
|
||||
|
||||
- def initialize(data)
|
||||
- @data = data
|
||||
+ class RawData < CommandData # :nodoc:
|
||||
+ def send_data(imap, tag)
|
||||
+ imap.send(:put_string, @data)
|
||||
end
|
||||
end
|
||||
|
||||
- class Atom # :nodoc:
|
||||
+ class Atom < CommandData # :nodoc:
|
||||
def send_data(imap, tag)
|
||||
imap.send(:put_string, @data)
|
||||
end
|
||||
@@ -1611,19 +1632,10 @@ def initialize(data)
|
||||
end
|
||||
end
|
||||
|
||||
- class Literal # :nodoc:
|
||||
+ class Literal < CommandData # :nodoc:
|
||||
def send_data(imap, tag)
|
||||
imap.send(:send_literal, @data, tag)
|
||||
end
|
||||
-
|
||||
- def validate
|
||||
- end
|
||||
-
|
||||
- private
|
||||
-
|
||||
- def initialize(data)
|
||||
- @data = data
|
||||
- end
|
||||
end
|
||||
|
||||
class MessageSet # :nodoc:
|
||||
|
||||
From 5c6f3ce364478fd8fde9fe8c9fc47cad34ac4ba7 Mon Sep 17 00:00:00 2001
|
||||
From: nick evans <nick@rubinick.dev>
|
||||
Date: Thu, 19 Feb 2026 15:06:08 -0500
|
||||
Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=8D=92=20pick=209db3e9d60:=20?=
|
||||
=?UTF-8?q?=F0=9F=A5=85=20Strictly=20validate=20symbol=20(\flag)=20argumen?=
|
||||
=?UTF-8?q?ts=20[backports=20#657]?=
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Flags should not allow `atom-specials`.
|
||||
|
||||
Previously, no validation was done on symbol data. Sending atom or flag
|
||||
args which contain atom specials could lead to various errors.
|
||||
|
||||
Although this could theoretically include injection attacks, this is not
|
||||
considered to be a critical vulnerability in `net-imap`, for the
|
||||
following reason: Valid "system flag" inputs are restricted to an
|
||||
enumerated set of RFC-defined flag types. User-defined "keyword" flags
|
||||
are sent as atoms, not flags, which use string inputs (strings which
|
||||
can't be sent as an atom will be quoted or sent as a literal). `\Seen`
|
||||
as a flag (symbol argument) is semantically different from `Seen` as a
|
||||
keyword (string argument). So there is no scenario where it is
|
||||
appropriate to call `#to_sym` on unvetted user input. Any code which
|
||||
calls `#to_sym` indiscriminately on user-input is already buggy.
|
||||
|
||||
Nevertheless, users should reasonably be able to rely on `net-imap` to
|
||||
do very basic input validation on its basic input types.
|
||||
|
||||
===
|
||||
|
||||
Tests were not backported, they use a much newer style that does not
|
||||
make sense to backport, when we can run the tests elsewhere instead of
|
||||
trying to essentially write some portions anew.
|
||||
---
|
||||
lib/net/imap.rb | 32 ++++++++++++++++++++++----------
|
||||
1 file changed, 22 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/lib/net/imap.rb b/lib/net/imap.rb
|
||||
index ba44d21956..4354731f13 100644
|
||||
--- a/lib/net/imap.rb
|
||||
+++ b/lib/net/imap.rb
|
||||
@@ -1344,6 +1344,7 @@ def validate_data(data)
|
||||
end
|
||||
when Time
|
||||
when Symbol
|
||||
+ Flag.validate(data)
|
||||
else
|
||||
data.validate
|
||||
end
|
||||
@@ -1362,7 +1363,7 @@ def send_data(data, tag = nil)
|
||||
when Time
|
||||
send_time_data(data)
|
||||
when Symbol
|
||||
- send_symbol_data(data)
|
||||
+ Flag[data].send_data(self, tag)
|
||||
else
|
||||
data.send_data(self, tag)
|
||||
end
|
||||
@@ -1432,10 +1433,6 @@ def send_time_data(time)
|
||||
put_string(s)
|
||||
end
|
||||
|
||||
- def send_symbol_data(symbol)
|
||||
- put_string("\\" + symbol.to_s)
|
||||
- end
|
||||
-
|
||||
def search_internal(cmd, keys, charset)
|
||||
if keys.instance_of?(String)
|
||||
keys = [RawData.new(keys)]
|
||||
@@ -1587,6 +1584,12 @@ def eql?(other) self.class === other && to_h.eql?(other.to_h) end
|
||||
# following class definition goes beyond the basic Data.define(:data)
|
||||
##
|
||||
|
||||
+ def self.validate(*args)
|
||||
+ data = new(*args)
|
||||
+ data.validate
|
||||
+ data
|
||||
+ end
|
||||
+
|
||||
def send_data(imap, tag)
|
||||
raise NoMethodError, "#{self.class} must implement #{__method__}"
|
||||
end
|
||||
@@ -1603,17 +1606,26 @@ def send_data(imap, tag)
|
||||
end
|
||||
|
||||
class Atom < CommandData # :nodoc:
|
||||
- def send_data(imap, tag)
|
||||
- imap.send(:put_string, @data)
|
||||
+ def initialize(**)
|
||||
+ super
|
||||
+ validate
|
||||
end
|
||||
|
||||
def validate
|
||||
+ data.to_s.ascii_only? \
|
||||
+ or raise DataFormatError, "#{self.class} must be ASCII only"
|
||||
+ data.match?(ResponseParser::Patterns::ATOM_SPECIALS) \
|
||||
+ and raise DataFormatError, "#{self.class} must not contain atom-specials"
|
||||
end
|
||||
|
||||
- private
|
||||
+ def send_data(imap, tag)
|
||||
+ imap.send(:put_string, data.to_s)
|
||||
+ end
|
||||
+ end
|
||||
|
||||
- def initialize(data)
|
||||
- @data = data
|
||||
+ class Flag < Atom # :nodoc:
|
||||
+ def send_data(imap, tag)
|
||||
+ imap.send(:put_string, "\\#{data}")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
From 1f8a99c432f748dfccb275cc696d8ac58c2255e6 Mon Sep 17 00:00:00 2001
|
||||
From: Jarek Prokop <jprokop@redhat.com>
|
||||
Date: Tue, 9 Jun 2026 18:14:51 +0200
|
||||
Subject: [PATCH 3/3] Cherry-pick ATOM_SPECIALS for validation regex.
|
||||
|
||||
The previous commit relies on ResponseParsers::Patterns::ATOM_SPECIALS
|
||||
to be available. We could either hardcode the regex in the line where
|
||||
the matching happens, but instead have it live in its own constant for
|
||||
easier reference and less edits to the actual commit backport.
|
||||
|
||||
The line ported from:
|
||||
https://github.com/ruby/net-imap/commit/92db350b24c388d2a2104f36cac9caa49a1044df
|
||||
---
|
||||
lib/net/imap.rb | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/lib/net/imap.rb b/lib/net/imap.rb
|
||||
index 4354731f13..2af43806bb 100644
|
||||
--- a/lib/net/imap.rb
|
||||
+++ b/lib/net/imap.rb
|
||||
@@ -2218,6 +2218,10 @@ def multipart?
|
||||
end
|
||||
|
||||
class ResponseParser # :nodoc:
|
||||
+ module Patterns
|
||||
+ ATOM_SPECIALS = /[(){ \x00-\x1f\x7f%*"\\\]]/n
|
||||
+ end
|
||||
+
|
||||
def initialize
|
||||
@str = nil
|
||||
@pos = nil
|
||||
@ -21,7 +21,7 @@
|
||||
%endif
|
||||
|
||||
|
||||
%global release 114
|
||||
%global release 115
|
||||
|
||||
%{!?release_string:%global release_string %{?development_release:0.}%{release}%{?development_release:.%{development_release}}%{?dist}}
|
||||
|
||||
@ -275,6 +275,18 @@ Patch50: rubygem-rexml-3.3.9-Fix-ReDoS-CVE-2024-49761.patch
|
||||
# https://github.com/kkos/oniguruma/issues/164#issuecomment-558134827
|
||||
# https://issues.redhat.com/browse/RHEL-87505
|
||||
Patch51: ruby-3.5.0-fix-164-Integer-overflow-related-to-reg-dmax-in-sear.patch
|
||||
# Fix CVE-2026-42246 Information disclosure via man-in-the-middle attack bypassing TLS.
|
||||
# Backport https://github.com/ruby/net-imap/pull/667 for net-imap 0.3.10,
|
||||
# it is closest to Ruby 2.5.9's net-imap.
|
||||
# For details, see commit notes 3 equal signs `===` in the patch.
|
||||
Patch52: rubygem-net-imap-0.3.10-Fix-Information-disclosure-via-man-in-the-middle-attack-bypassing-TLS-CVE-2026-42246.patch
|
||||
# Fix CVE-2026-42258 IMAP Command Injection via Symbol Arguments.
|
||||
# https://github.com/ruby/net-imap/commit/1eb27278a601be1135910dae6ab6e517559a2e4a
|
||||
# https://github.com/ruby/net-imap/commit/bbd9eb7ecca506fa43b656368f7aebef8ac09182
|
||||
# Additionally, backport validation regex ATOM_SPECIALS that's needed, from
|
||||
# https://github.com/ruby/net-imap/commit/92db350b24c388d2a2104f36cac9caa49a1044df
|
||||
# For details, see commit notes 3 equal signs `===` in the patch.
|
||||
Patch53: rubygem-net-imap-0.4.24-Fix-IMAP-Command-Injection-via-Symbol-Arguments-CVE-2026-42258.patch
|
||||
|
||||
|
||||
Requires: %{name}-libs%{?_isa} = %{version}-%{release}
|
||||
@ -697,6 +709,8 @@ sed -i 's/"evaluation\/incorrect_words.yaml"\.freeze, //' \
|
||||
%patch49 -p1
|
||||
%patch50 -p1
|
||||
%patch51 -p1
|
||||
%patch52 -p1
|
||||
%patch53 -p1
|
||||
|
||||
# Provide an example of usage of the tapset:
|
||||
cp -a %{SOURCE3} .
|
||||
@ -1261,6 +1275,13 @@ OPENSSL_SYSTEM_CIPHERS_OVERRIDE=xyz_nonexistent_file OPENSSL_CONF='' \
|
||||
%{gem_dir}/specifications/xmlrpc-%{xmlrpc_version}.gemspec
|
||||
|
||||
%changelog
|
||||
* Thu Jun 11 2026 Jarek Prokop <jprokop@redhat.com> - 2.5.9-115
|
||||
- Fix information disclosure via MITM attack bypassing TLS in net-imap.
|
||||
(CVE-2026-42246)
|
||||
Resolves: RHEL-181772
|
||||
- Fix command injection via Symbol arguments in net-imap. (CVE-2026-42258)
|
||||
Resolves: RHEL-181792
|
||||
|
||||
* Mon May 05 2025 Vít Ondruch <vondruch@redhat.com> - 2.5.9-114
|
||||
- Fix integer overflow in search_in_range function in regexec.c (CVE-2019-19012).
|
||||
Resolves: RHEL-87505
|
||||
|
||||
Loading…
Reference in New Issue
Block a user