Fix arbitrary code execution via deserialization bypass in ERB.
Fix CVE-2026-41316.
ef61b591b2
Resolves: RHEL-171256
This commit is contained in:
parent
f77e9e6b4e
commit
cfc70379c4
10
ruby.spec
10
ruby.spec
@ -22,7 +22,7 @@
|
||||
%endif
|
||||
|
||||
|
||||
%global release 165
|
||||
%global release 166
|
||||
%{!?release_string:%define release_string %{?development_release:0.}%{release}%{?development_release:.%{development_release}}%{?dist}}
|
||||
|
||||
# The RubyGems library has to stay out of Ruby directory tree, since the
|
||||
@ -344,6 +344,9 @@ Patch79: rubygem-openssl-3.3.0-test_asn1.rb-Remove-the-assertions-of-the-time.pa
|
||||
# Fix test_session_reuse_but_expire test failure for Net::HTTPS.
|
||||
# https://github.com/ruby/ruby/commit/9f4b45fbf7981a57fd82436ebec8a50ec3d3fdc9
|
||||
Patch80: ruby-3.4.0-ruby-net-http-test_https.rb-fix-test_session_reuse_but_expire.patch
|
||||
# Fix arbitrary code execution via deserialization bypass in ERB. (CVE-2026-41316)
|
||||
# https://github.com/ruby/erb/commit/ef61b591b270f8ba58d47f12472a1c53a77b4d61
|
||||
Patch81: rubygem-erb-4.0.3.1-Fix-arbitrary-code-execution-via-deserialization-bypass-CVE-2026-41316.patch
|
||||
|
||||
Requires: %{name}-libs%{?_isa} = %{version}-%{release}
|
||||
Suggests: rubypick
|
||||
@ -826,6 +829,7 @@ rm -rf ext/fiddle/libffi*
|
||||
%patch78 -p1
|
||||
%patch79 -p1
|
||||
%patch80 -p1
|
||||
%patch81 -p1
|
||||
|
||||
# Instead of adjusting patch's directory, use the following form where
|
||||
# we first enter the correct directory, this allows more general application
|
||||
@ -1608,6 +1612,10 @@ make runruby TESTRUN_SCRIPT=" \
|
||||
|
||||
|
||||
%changelog
|
||||
* Mon Apr 27 2026 Jarek Prokop <jprokop@redhat.com> - 3.0.7-166
|
||||
- Fix arbitrary code execution via deserialization bypass in ERB. (CVE-2026-41316)
|
||||
Resolves: RHEL-171256
|
||||
|
||||
* Fri Apr 11 2025 Jarek Prokop <jprokop@redhat.com> - 3.0.7-165
|
||||
- Fix Denial of Service in CGI::Cookie.parse. (CVE-2025-27219)
|
||||
Resolves: RHEL-86104
|
||||
|
||||
@ -0,0 +1,68 @@
|
||||
From 9bdf63dd97e56edd9eba4e2a95623798ed472d86 Mon Sep 17 00:00:00 2001
|
||||
From: Takashi Kokubun <takashikkbn@gmail.com>
|
||||
Date: Tue, 21 Apr 2026 16:27:44 +0900
|
||||
Subject: [PATCH] Prohibit def_method on marshal-loaded ERB instances
|
||||
|
||||
Extends the @_init guard to def_method so that an ERB object created
|
||||
via Marshal.load (which bypasses initialize) raises ArgumentError
|
||||
instead of evaluating arbitrary source. def_module and def_class both
|
||||
delegate to def_method and are covered by the same check.
|
||||
|
||||
Co-authored-by: Tristan Madani <TristanInSec@gmail.com>
|
||||
---
|
||||
lib/erb.rb | 3 +++
|
||||
test/erb/test_erb.rb | 27 +++++++++++++++++++++++++++
|
||||
2 files changed, 30 insertions(+)
|
||||
|
||||
diff --git a/lib/erb.rb b/lib/erb.rb
|
||||
index d2ea64ab60..6c5efad513 100644
|
||||
--- a/lib/erb.rb
|
||||
+++ b/lib/erb.rb
|
||||
@@ -939,6 +939,9 @@ def new_toplevel(vars = nil)
|
||||
# erb.def_method(MyClass, 'render(arg1, arg2)', filename)
|
||||
# print MyClass.new.render('foo', 123)
|
||||
def def_method(mod, methodname, fname='(ERB)')
|
||||
+ unless @_init.equal?(self.class.singleton_class)
|
||||
+ raise ArgumentError, "not initialized"
|
||||
+ end
|
||||
src = self.src.sub(/^(?!#|$)/) {"def #{methodname}\n"} << "\nend\n"
|
||||
mod.module_eval do
|
||||
eval(src, binding, fname, -1)
|
||||
diff --git a/test/erb/test_erb.rb b/test/erb/test_erb.rb
|
||||
index d3e9b6c944..e5f2d97f1c 100644
|
||||
--- a/test/erb/test_erb.rb
|
||||
+++ b/test/erb/test_erb.rb
|
||||
@@ -701,6 +701,33 @@ def test_prohibited_marshal_load
|
||||
erb = Marshal.load(Marshal.dump(erb))
|
||||
assert_raise(ArgumentError) {erb.result}
|
||||
end
|
||||
+
|
||||
+ def test_prohibited_marshal_load_def_method
|
||||
+ erb = ERB.allocate
|
||||
+ erb.instance_variable_set(:@src, "")
|
||||
+ erb.instance_variable_set(:@lineno, 1)
|
||||
+ erb.instance_variable_set(:@_init, true)
|
||||
+ erb = Marshal.load(Marshal.dump(erb))
|
||||
+ assert_raise(ArgumentError) {erb.def_method(Class.new, 'render')}
|
||||
+ end
|
||||
+
|
||||
+ def test_prohibited_marshal_load_def_module
|
||||
+ erb = ERB.allocate
|
||||
+ erb.instance_variable_set(:@src, "")
|
||||
+ erb.instance_variable_set(:@lineno, 1)
|
||||
+ erb.instance_variable_set(:@_init, true)
|
||||
+ erb = Marshal.load(Marshal.dump(erb))
|
||||
+ assert_raise(ArgumentError) {erb.def_module}
|
||||
+ end
|
||||
+
|
||||
+ def test_prohibited_marshal_load_def_class
|
||||
+ erb = ERB.allocate
|
||||
+ erb.instance_variable_set(:@src, "")
|
||||
+ erb.instance_variable_set(:@lineno, 1)
|
||||
+ erb.instance_variable_set(:@_init, true)
|
||||
+ erb = Marshal.load(Marshal.dump(erb))
|
||||
+ assert_raise(ArgumentError) {erb.def_class}
|
||||
+ end
|
||||
end
|
||||
|
||||
class TestERBCoreWOStrScan < TestERBCore
|
||||
Loading…
Reference in New Issue
Block a user