diff --git a/ruby.spec b/ruby.spec index ed27e74..61bf0d8 100644 --- a/ruby.spec +++ b/ruby.spec @@ -310,6 +310,13 @@ Patch18: rubygem-net-imap-0.4.24-DoS-via-crafted-IMAP-responses-CVE-2026-42245.p # https://github.com/ruby/net-imap/commit/705aa59 # https://github.com/ruby/net-imap/commit/038ae35 Patch19: rubygem-net-imap-0.4.24-Information-disclosure-via-MITM-attack-bypassing-TLS-2026-42246.patch +# Tests not included, the gem does not have tests in the ruby tar. +# Original source PR#663 but it bunches more fixes together, so we backport less. +# https://github.com/ruby/net-imap/pull/663 +# Backported from the following, the first commit below is requirement for the actual fix: +# https://github.com/ruby/net-imap/commit/1eb27278a601be1135910dae6ab6e517559a2e4a +# https://github.com/ruby/net-imap/commit/bbd9eb7ecca506fa43b656368f7aebef8ac09182 +Patch20: rubygem-net-imap-0.4.24-Command-Injection-via-Symbol-Arguments-CVE-2026-42258.patch Requires: %{name}-libs%{?_isa} = %{version}-%{release} %{?with_rubypick:Suggests: rubypick} @@ -798,6 +805,7 @@ analysis result in RBS format, a standard type description format for Ruby pushd .bundle/gems/net-imap-%{net_imap_version} %patch 18 -p1 %patch 19 -p1 +%patch 20 -p1 popd # Provide an example of usage of the tapset: @@ -1810,6 +1818,8 @@ make -C %{_vpath_builddir} runruby TESTRUN_SCRIPT=" \ - Fix information disclosure via MITM attack bypassing TLS in net-imap. (CVE-2026-42246) Resolves: RHEL-181769 +- Fix command injection via Symbol arguments in net-imap. (CVE-2026-42258) + Resolves: RHEL-181799 * Tue Apr 28 2026 Jarek Prokop - 3.3.10-12 - Fix arbitrary code execution via deserialization bypass in ERB. (CVE-2026-41316) diff --git a/rubygem-net-imap-0.4.24-Command-Injection-via-Symbol-Arguments-CVE-2026-42258.patch b/rubygem-net-imap-0.4.24-Command-Injection-via-Symbol-Arguments-CVE-2026-42258.patch new file mode 100644 index 0000000..2c1d493 --- /dev/null +++ b/rubygem-net-imap-0.4.24-Command-Injection-via-Symbol-Arguments-CVE-2026-42258.patch @@ -0,0 +1,209 @@ +From e55d73b170eb4a5523a411cdc9bd5cf13121694e Mon Sep 17 00:00:00 2001 +From: nick evans +Date: Wed, 22 Apr 2026 11:25:06 -0400 +Subject: [PATCH 1/2] =?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/command_data.rb | 50 +++++++++++++++++++----------------- + 1 file changed, 26 insertions(+), 24 deletions(-) + +diff --git a/lib/net/imap/command_data.rb b/lib/net/imap/command_data.rb +index 180a254..91c7336 100644 +--- a/lib/net/imap/command_data.rb ++++ b/lib/net/imap/command_data.rb +@@ -119,33 +119,44 @@ module Net + put_string("\\" + symbol.to_s) + end + +- class RawData # :nodoc: +- def send_data(imap, tag) +- imap.__send__(:put_string, @data) ++ # simplistic emulation of CommandData = Data.define(:data) ++ class CommandData # :nodoc: ++ class << self ++ def new(arg = nil, data: arg) super(data: data) end ++ alias :[] :new + end + +- def validate ++ def initialize(data:) ++ @data = data ++ freeze + end + +- private ++ attr_reader :data + +- def initialize(data) +- @data = data +- end +- end ++ 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) ++ ## + +- class Atom # :nodoc: + def send_data(imap, tag) +- imap.__send__(:put_string, @data) ++ raise NoMethodError, "#{self.class} must implement #{__method__}" + end + + def validate + end ++ end + +- private ++ class RawData < CommandData # :nodoc: ++ def send_data(imap, tag) ++ imap.__send__(:put_string, @data) ++ end ++ end + +- def initialize(data) +- @data = data ++ class Atom < CommandData # :nodoc: ++ def send_data(imap, tag) ++ imap.__send__(:put_string, @data) + end + end + +@@ -164,19 +175,10 @@ module Net + 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 d1c362631589b20e59f5e64fe1ee9222b3ea07f9 Mon Sep 17 00:00:00 2001 +From: nick evans +Date: Thu, 19 Feb 2026 15:06:08 -0500 +Subject: [PATCH 2/2] =?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. +--- + lib/net/imap/command_data.rb | 33 +++++++++++++++++++++++++++------ + 1 file changed, 27 insertions(+), 6 deletions(-) + +diff --git a/lib/net/imap/command_data.rb b/lib/net/imap/command_data.rb +index 91c7336..499002f 100644 +--- a/lib/net/imap/command_data.rb ++++ b/lib/net/imap/command_data.rb +@@ -25,6 +25,7 @@ module Net + end + when Time, Date, DateTime + when Symbol ++ Flag.validate(data) + else + data.validate + end +@@ -45,7 +46,7 @@ module Net + when Date + send_date_data(data) + when Symbol +- send_symbol_data(data) ++ Flag[data].send_data(self, tag) + else + data.send_data(self, tag) + end +@@ -115,10 +116,6 @@ module Net + def send_date_data(date) put_string Net::IMAP.encode_date(date) end + def send_time_data(time) put_string Net::IMAP.encode_time(time) end + +- def send_symbol_data(symbol) +- put_string("\\" + symbol.to_s) +- end +- + # simplistic emulation of CommandData = Data.define(:data) + class CommandData # :nodoc: + class << self +@@ -140,6 +137,12 @@ module Net + # following class definition goes beyond the basic Data.define(:data) + ## + ++ def self.validate(...) ++ data = new(...) ++ data.validate ++ data ++ end ++ + def send_data(imap, tag) + raise NoMethodError, "#{self.class} must implement #{__method__}" + end +@@ -155,8 +158,26 @@ module Net + end + + class Atom < CommandData # :nodoc: ++ 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 ++ + def send_data(imap, tag) +- imap.__send__(:put_string, @data) ++ imap.__send__(:put_string, data.to_s) ++ end ++ end ++ ++ class Flag < Atom # :nodoc: ++ def send_data(imap, tag) ++ imap.__send__(:put_string, "\\#{data}") + end + end +