CVE-2026-95521: Rpm: rpm: shell command injection via macro expansion of source/spec file basenames when installing a source rpm
A command injection flaw was found in rpm. Installing or rebuilding a source RPM whose source or spec file basenames contain a %() macro construct causes rpm to execute an attacker-controlled shell command via popen() while relocating the source file list. This allows arbitrary command execution as the invoking (typically non-root) user, simply by installing, rebuilding, or otherwise processing an untrusted .src.rpm.
Other sources
A command injection flaw was found in rpm. The macro engine's %() construct executes an embedded shell command via popen() whenever the macro text is expanded, regardless of where that text came from (rpmio/macro.cc: case '(' at :1678 calls doShellEscape(), which ends in popen(buf, "r") at :499). Installing or rebuilding a .src.rpm routes through rpmInstallSourcePackage(), whose getFiles() calls rpmRelocateSrpmFileList() (lib/relocation.cc:454); that function builds the destination path for every source and spec file with rpmGenPath(rootDir, "%{specdir}"|"%{sourcedir}", bn), and joinpath() (rpmio/rpmfileutil.cc:463) macro-expands each path component individually, including the package-supplied basename bn. A source or spec basename containing a %(cmd) construct is therefore expanded and the embedded command executed. This install path never calls rpmtsRun(), so %pkgverifylevel provides no protection: rpmReadPackageFile() hard-codes vfylevel to 0 (lib/package.cc:315) and accepts a completely unsigned .src.rpm under the distro-default policy, and rpm -i still reports success (exit 0) with nothing to indicate a command ran. rpmbuild --rebuild reaches the same relocation code during install, before any mock/chroot sandbox boundary. This was confirmed by reproducing the reporter's proof of concept with an AddressSanitizer-instrumented build of rpm at both rpm-6.1.0-release and master: rpm -i against a crafted, unsigned .src.rpm silently ran an embedded canary command while the install still exited 0, including with %pkgverifylevel all set, which shows signature policy is not the gate; negative controls (removing the leading %, or using rpm -qpl instead of installing) did not execute the command.
— Red Hat
Affected Software
Event History
Frequently Asked Questions
Who is realistically exposed to this issue?
Users or automated workflows that install, rebuild, or otherwise process untrusted source RPMs are exposed. Commands run as the user invoking rpm, which is typically a non-root user.
What does an attacker need to exploit it?
An attacker needs to provide a source RPM with a source or spec file basename containing a %() macro construct and have a victim process that .src.rpm. The vulnerable processing path expands the attacker-supplied basename and executes the embedded shell command.
Which actions can trigger the command execution?
Installing or rebuilding a malicious source RPM can trigger it. The issue may also be reached through other processing of an untrusted .src.rpm that relocates its source file list.
What can be done if patching is not immediately possible?
Do not install, rebuild, or otherwise process untrusted source RPMs. Before processing a source RPM, treat source and spec filenames containing %() constructs as unsafe.