From c9d28261cecc434cbf58c2fb4cbba240ac885a60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Josef=20=C5=A0pa=C4=8Dek?= Date: Fri, 12 Jun 2026 12:27:23 +0200 Subject: [PATCH] Resolves arbitrary code execution via attacker-controlled output glob (CVE-2026-48962) Resolves: RHEL-180421 --- ...096-remove_use_of_eval_in_globmapper.patch | 160 ++++++++++++++++++ perl-IO-Compress.spec | 8 +- 2 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 IO-Compress-2.096-remove_use_of_eval_in_globmapper.patch diff --git a/IO-Compress-2.096-remove_use_of_eval_in_globmapper.patch b/IO-Compress-2.096-remove_use_of_eval_in_globmapper.patch new file mode 100644 index 0000000..d68ff4b --- /dev/null +++ b/IO-Compress-2.096-remove_use_of_eval_in_globmapper.patch @@ -0,0 +1,160 @@ +From f2db247bf90d4cc7ee2710be384946081f3b4610 Mon Sep 17 00:00:00 2001 +From: pmqs +Date: Sat, 16 May 2026 17:48:34 +0100 +Subject: [PATCH] remove use of eval in globmapper. #73 + +--- + lib/File/GlobMapper.pm | 52 ++++++++++++++++++++++++++++++++++-------- + t/globmapper.t | 52 +++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 94 insertions(+), 10 deletions(-) + +diff -u -r IO-Compress-2.096.orig/lib/File/GlobMapper.pm IO-Compress-2.096/lib/File/GlobMapper.pm +--- IO-Compress-2.096.orig/lib/File/GlobMapper.pm 2026-06-12 12:18:53.933423914 +0200 ++++ IO-Compress-2.096/lib/File/GlobMapper.pm 2026-06-12 12:22:04.236128335 +0200 +@@ -29,6 +29,11 @@ + $VERSION = '1.001'; + @EXPORT_OK = qw( globmap ); + ++our $BEGIN_DELIM = "\xFF"; ++our $END_DELIM = "\xFE"; ++our $BACKSLASH_ESC = "\xFD"; ++our $HASH_ESC = "\xFC"; ++our $STAR_ESC = "\xFB"; + + our ($noPreBS, $metachars, $matchMetaRE, %mapping, %wildCount); + $noPreBS = '(?{InputPattern}'\n"; ++ # print "OUTPUT '$self->{OutputGlob}' => '$string'\n"; + +- #print "OUTPUT '$self->{OutputGlob}' => '$string'\n"; + $self->{OutputPattern} = $string ; + + return 1 ; +@@ -335,11 +349,31 @@ + next if $inFiles{$inFile} ++ ; + + my $outFile = $inFile ; ++ my @matches ; ++ ++ my $noPreESC = '(?{InputPattern}/ ) ++ if (@matches = ($inFile =~ m/$self->{InputPattern}/ )) + { +- no warnings 'uninitialized'; +- eval "\$outFile = $self->{OutputPattern};" ; ++ $outFile = $self->{OutputPattern}; ++ my $ix = 1; ++ ++ # get the filename glob ++ $outFile =~ s/${noPreESC}${BEGIN_DELIM}${END_DELIM}/$inFile/g; ++ ++ # now each of the #1, #2,... ++ for my $pattern (@matches) ++ { ++ $outFile =~ s/${noPreESC}${BEGIN_DELIM}${ix}${END_DELIM}/$pattern/g; ++ ++ ++ $ix; ++ } ++ ++ # unescape ++ $outFile =~ s/${BEGIN_DELIM}${BEGIN_DELIM}/${BEGIN_DELIM}/g; ++ $outFile =~ s/${END_DELIM}${END_DELIM}/${END_DELIM}/g; ++ $outFile =~ s/${HASH_ESC}/#/g; ++ $outFile =~ s/${STAR_ESC}/*/g; + + if (defined $outInMapping{$outFile}) + { +diff -u -r IO-Compress-2.096.orig/t/globmapper.t IO-Compress-2.096/t/globmapper.t +--- IO-Compress-2.096.orig/t/globmapper.t 2026-06-12 12:18:53.938987087 +0200 ++++ IO-Compress-2.096/t/globmapper.t 2026-06-12 12:22:04.238128347 +0200 +@@ -24,7 +24,7 @@ + $extra = 1 + if eval { require Test::NoWarnings ; import Test::NoWarnings; 1 }; + +- plan tests => 68 + $extra ; ++ plan tests => 76 + $extra ; + + use_ok('File::GlobMapper') ; + } +@@ -290,6 +290,56 @@ + ], " got mapping"; + } + ++{ ++ title "check escaping"; ++ ++ my $tmpDir ;#= 'td'; ++ my $lex = LexDir->new( $tmpDir ); ++ ++ my $BEGIN_DELIM = "\xFF"; ++ my $END_DELIM = "\xFE"; ++ ++ #mkdir $tmpDir, 0777 ; ++ ++ touch map { "$tmpDir/$_.tmp" } qw( abc1 abc2 abc3 ) ; ++ ++ my $map = File::GlobMapper::globmap("$tmpDir/*b*.tmp", "$tmpDir/X-${BEGIN_DELIM}#2-#1${END_DELIM}-X"); ++ ok $map, " got map" ++ or diag $File::GlobMapper::Error ; ++ ++ is @{ $map }, 3, " returned 3 maps"; ++ is_deeply $map, ++ [ [map { "$tmpDir/$_" } ("abc1.tmp", "X-${BEGIN_DELIM}c1-a${END_DELIM}-X")], ++ [map { "$tmpDir/$_" } ("abc2.tmp", "X-${BEGIN_DELIM}c2-a${END_DELIM}-X")], ++ [map { "$tmpDir/$_" } ("abc3.tmp", "X-${BEGIN_DELIM}c3-a${END_DELIM}-X")], ++ ], " got mapping"; ++} ++ ++{ ++ title "check backslash escaping"; ++ ++ my $tmpDir ;#= 'td'; ++ my $lex = LexDir->new( $tmpDir ); ++ ++ my $BEGIN_DELIM = "\xFF"; ++ my $END_DELIM = "\xFE"; ++ ++ #mkdir $tmpDir, 0777 ; ++ ++ touch map { "$tmpDir/$_.tmp" } qw( abc1 abc2 abc3 ) ; ++ ++ my $map = File::GlobMapper::globmap("$tmpDir/*b*.tmp", $tmpDir . '/X-#2-\\#1\\*-X'); ++ ok $map, " got map" ++ or diag $File::GlobMapper::Error ; ++ ++ is @{ $map }, 3, " returned 3 maps"; ++ is_deeply $map, ++ [ [map { "$tmpDir/$_" } ("abc1.tmp", "X-c1-#1*-X")], ++ [map { "$tmpDir/$_" } ("abc2.tmp", "X-c2-#1*-X")], ++ [map { "$tmpDir/$_" } ("abc3.tmp", "X-c3-#1*-X")], ++ ], " got mapping"; ++} ++ + # TODO + # test each of the wildcard metacharacters can be mapped to the output filename + # +Pouze v IO-Compress-2.096/t: globmapper.t.orig diff --git a/perl-IO-Compress.spec b/perl-IO-Compress.spec index 4ad1f2b..84e3c63 100644 --- a/perl-IO-Compress.spec +++ b/perl-IO-Compress.spec @@ -11,11 +11,12 @@ Name: perl-IO-Compress Version: 2.096 -Release: 1%{?dist} +Release: 2%{?dist} Summary: Read and write compressed data License: GPL+ or Artistic URL: https://metacpan.org/release/IO-Compress Source0: https://cpan.metacpan.org/modules/by-module/IO/IO-Compress-%{version}.tar.gz +Patch0: IO-Compress-2.096-remove_use_of_eval_in_globmapper.patch BuildArch: noarch # Module Build BuildRequires: coreutils @@ -93,6 +94,7 @@ included with the IO-Compress distribution: %prep %setup -q -n IO-Compress-%{version} +%patch -P0 -p1 # Remove spurious exec permissions chmod -c -x lib/IO/Uncompress/{Adapter/Identity,RawInflate}.pm @@ -144,6 +146,10 @@ make test COMPRESS_ZLIB_RUN_%{?with_long_tests:ALL}%{!?with_long_tests:MOST}=1 %{_mandir}/man3/IO::Uncompress::*.3* %changelog +* Fri Jun 12 2026 Michal Josef Špaček - 2.096-2 +- Resolves arbitrary code execution via attacker-controlled output glob (CVE-2026-48962) + Resolves: RHEL-180421 + * Sat Aug 1 2020 Paul Howarth - 2.096-1 - 2.096 bump