Fix CVE-2026-8450: send_file() RCE via 2-arg open() shell-magic

Backport upstream fix (commit 945d351) for CVE-2026-8450 in
perl-HTTP-Daemon. The send_file() method used 2-arg open()
which allowed shell-magic interpretation of filenames (pipe
commands, redirections), enabling RCE and arbitrary file write
when filenames were derived from attacker-controlled input.
The fix switches to 3-arg open() with explicit '<' mode,
adds binmode error handling, and returns '0E0' for
empty-but-successful transfers.

CVE: CVE-2026-8450
Upstream patches:
 - 945d35141d.patch
Resolves: RHEL-184821

This commit was backported by Ymir, a Red Hat Enterprise Linux software maintenance AI agent.

Assisted-by: Ymir
This commit is contained in:
RHEL Packaging Agent 2026-08-05 13:11:57 +00:00
parent 25c071a09c
commit 73c2c63253
2 changed files with 117 additions and 1 deletions

View File

@ -0,0 +1,108 @@
From 04756e6d63242b15e26d8c2bb988668e810433e8 Mon Sep 17 00:00:00 2001
From: Olaf Alders <olaf@wundersolutions.com>
Date: Thu, 14 May 2026 00:09:58 +0000
Subject: [PATCH] Fix CVE-2026-8450: send_file() honoured 2-arg open()
shell-magic
HTTP::Daemon::ClientConn::send_file() used the 2-arg form
open(FILE, $file), which interprets shell-magic prefixes in the
path argument: '| cmd' (write pipe -- RCE), 'cmd |' (read pipe --
RCE plus response-body exfiltration via the sysread / print loop
below), '> path' (write-truncate -- arbitrary file write), and
'>> path', '+< path', '<&fd', and leading-whitespace variants of
the above.
Any HTTP::Daemon-based application that passed attacker-influenced
bytes to send_file($string) -- for example, a download endpoint
that derived the filename from a query parameter -- granted command
execution and/or arbitrary file write at the daemon's UID.
Switch to 3-arg open(my $fh, '<', $file): the explicit '<' mode
makes the path argument a literal filename, so every magic shape
above is opened (and fails, returning undef) as an ordinary file by
that exact name. The localized typeglob is no longer needed and is
replaced with a lexical filehandle.
Two collateral hardening changes ride along:
- binmode() failure now closes the handle and returns undef,
rather than streaming the file with a wrong PerlIO layer.
- send_file() returns '0E0' (true zero) on a successful zero-byte
transfer so callers using "send_file or die" can distinguish
open failure (undef) from an empty-but-successful copy.
The POD now documents the new return-value contract and spells
out that the fix only neutralises 2-arg open() shell-magic;
callers remain responsible for validating attacker-influenced
paths against symlinks, character/block devices (e.g. /dev/zero),
named pipes, and document-root escapes.
Reported and patched by Stig Palmquist (stigtsp).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---
lib/HTTP/Daemon.pm | 35 ++++++++++++++++++++++++++++++-----
1 file changed, 30 insertions(+), 5 deletions(-)
diff --git a/lib/HTTP/Daemon.pm b/lib/HTTP/Daemon.pm
index f9b3216..0707b9b 100644
--- a/lib/HTTP/Daemon.pm
+++ b/lib/HTTP/Daemon.pm
@@ -592,11 +592,10 @@ sub send_dir {
sub send_file {
my ($self, $file) = @_;
my $opened = 0;
- local (*FILE);
if (!ref($file)) {
- open(FILE, $file) || return undef;
- binmode(FILE);
- $file = \*FILE;
+ open(my $fh, '<', $file) || return undef;
+ binmode($fh) || do { close($fh); return undef };
+ $file = $fh;
$opened++;
}
my $cnt = 0;
@@ -608,7 +607,11 @@ sub send_file {
print $self $buf;
}
close($file) if $opened;
- $cnt;
+
+ # Return a "true zero" for empty-but-successful copies so callers
+ # using `send_file or die` can distinguish open failure (undef)
+ # from a successful zero-byte transfer.
+ $cnt || '0E0';
}
sub daemon {
@@ -902,6 +905,28 @@ Copy the file to the client. The file can be a string (which
will be interpreted as a filename) or a reference to an C<IO::Handle>
or glob.
+Returns the number of bytes copied on success, or C<undef> if the
+filename form failed to open. An empty file returns the string
+C<'0E0'> (zero numerically, true in boolean context) so that callers
+using C<< send_file or die >> can distinguish open failure from a
+successful zero-byte transfer.
+
+The filename form uses Perl's 3-argument C<open> with an explicit C<<
+< >> mode, so the path is no longer interpreted as a 2-argument
+C<open> shell-magic shape such as C<< | cmd >>, C<< cmd | >>, or
+C<< > path >>. See
+L<CVE-2026-8450|https://www.cve.org/CVERecord?id=CVE-2026-8450> for
+the prior 2-argument C<open> behaviour this replaces.
+
+Note that this fix only neutralises 2-argument C<open> shell-magic.
+Callers remain responsible for validating attacker-influenced paths:
+C<send_file> will still happily open symlinks, character/block devices
+(e.g. C</dev/zero>, C</dev/stdin>), named pipes (which may block the
+worker), and files outside an intended document root. If C<$filename>
+can be derived from request input, validate it (canonicalise, reject
+C<..> segments, require C<-f _> and a vetted prefix) before passing it
+in.
+
=item $c->daemon
Return a reference to the corresponding C<HTTP::Daemon> object.

View File

@ -3,13 +3,16 @@
Name: perl-HTTP-Daemon
Version: 6.16
Release: 7%{?dist}
Release: 8%{?dist}
Summary: Simple HTTP server class
License: GPL-1.0-or-later OR Artistic-1.0-Perl
URL: https://metacpan.org/release/HTTP-Daemon
Source0: https://cpan.metacpan.org/authors/id/O/OA/OALDERS/HTTP-Daemon-%{version}.tar.gz
# Use Makefile.PL without unneeded dependencies
Patch0: HTTP-Daemon-6.04-EU-MM-is-not-deprecated.patch
# https://issues.redhat.com/browse/RHEL-184821
# https://github.com/libwww-perl/HTTP-Daemon/commit/945d35141d94490f749640bd4390acd6a2193995
Patch1: perl-HTTP-Daemon-6.16-CVE-2026-8450.patch
BuildArch: noarch
BuildRequires: coreutils
BuildRequires: make
@ -83,6 +86,7 @@ with "%{_libexecdir}/%{name}/test".
%prep
%setup -q -n HTTP-Daemon-%{version}
%patch -P0 -p1
%patch -P1 -p1
# Help generators to recognize Perl scripts
for F in $(find t/ -name '*.t'); do
perl -i -MConfig -ple 'print $Config{startperl} if $. == 1 && !s{\A#!\s*perl}{$Config{startperl}}' "$F"
@ -118,6 +122,10 @@ make test
%{_libexecdir}/%{name}
%changelog
* Wed Aug 05 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 6.16-8
- Fix CVE-2026-8450: send_file() shell-magic via 2-arg open()
Resolves: RHEL-184821
* Tue Oct 29 2024 Troy Dawson <tdawson@redhat.com> - 6.16-7
- Bump release for October 2024 mass rebuild:
Resolves: RHEL-64018