Bug 2527527

Summary: CVE-2026-84233 rpm: Command Execution via Macro Expansion in `rpmuncompress -x` for Crafted `.gem` Filenames [fedora-all]
Product: [Fedora] Fedora Reporter: Vladimir Vasilev <vvasilev>
Component: rpmAssignee: Panu Matilainen <pmatilai>
Status: NEW --- QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: medium Docs Contact:
Priority: medium    
Version: rawhideCC: igor.raits, mdomonko, packaging-team-maint, pmatilai
Target Milestone: ---Keywords: Security, SecurityTracking
Target Release: ---Flags: fedora-admin-xmlrpc: mirror+
Hardware: Unspecified   
OS: Unspecified   
Whiteboard: {"flaws": ["0656833d-c2b2-459f-bbcb-90dcfb3dbcac"]}
Fixed In Version: Doc Type: ---
Doc Text:
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:    
Bug Blocks: 2478409    

Description Vladimir Vasilev 2026-09-02 15:11:31 UTC
Disclaimer: Community trackers are created by Red Hat Product Security team on a best effort basis. Package maintainers are required to ascertain if the flaw indeed affects their package, before starting the update process.

AI_ONLY_REPORT
package: rpm-4.19.1.1-23.el10
------
Summary: Command Execution via Macro Expansion in `rpmuncompress -x` for  
Crafted `.gem` Filenames: attacker-controlled `.gem` basenames reach  
`rpmExpand()` through `rpmGetPath()`, allowing `%()` shell macro execution  
while the extraction command is being constructed.
Requirements to exploit: An attacker must supply a crafted `.gem` filename  
containing RPM macro syntax such as `%(...)`, and a user or automated  
workflow must invoke `rpmuncompress -x` on that file. No prior privileges  
are required, but any resulting command runs with the privileges of the  
invoking account.
Component affected: `rpm-4.19.1.1-23.el10`, `tools/rpmuncompress.c`  
(`doUntar()` `.gem` handling), with the expansion sink in  
`rpmio/rpmfileutil.c` (`rpmGetPath()`) and shell execution in  
`rpmio/macro.c` (`doShellEscape()`).
Version affected: `rpm-4.19.1.1-23.el10`
Patch available: no released package fix established; proposed patch  
included below
Version fixed: unknown
Upstream coordination: Not notified.
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 - Exploitation requires local access to provide a crafted filename  
to `rpmuncompress`; no remote trigger is established from the available  
evidence.
AC:L - Once a crafted `.gem` filename is processed, no race, bypass, or  
special environmental condition is needed.
PR:N - The attacker does not need an existing account or elevated  
privileges to create or supply the malicious file.
UI:R - A user or automated build workflow must invoke `rpmuncompress -x`  
on the crafted filename.
S:U - The vulnerable helper and the resulting command execution occur  
within the same security scope.
C:H - Successful exploitation can execute arbitrary commands and read  
data accessible to the invoking user or build account.
I:H - Arbitrary commands can modify files, outputs, and state reachable  
by the invoking user or build account.
A:H - Arbitrary commands can delete data, terminate processes, or  
otherwise disrupt work in that user context.
Impact: Important. This issue does not meet Red Hat's Critical criteria  
because exploitation is not remote and requires user or workflow  
interaction with a crafted local filename. It is stronger than Moderate  
because, once the vulnerable `.gem` extraction path is exercised, the  
attacker gains arbitrary command execution in the invoking account's  
context and can directly compromise the confidentiality, integrity, and  
availability of resources available to that account.
Embargo: no
Reason: The flaw requires a crafted local filename and user or build  
interaction, and practical short-term mitigations are available by avoiding  
or renaming untrusted `.gem` inputs before extraction. The available  
evidence does not indicate a need for embargoed handling.
Acknowledgement: Aisle Research
Vulnerability Details: When `rpmuncompress` handles a `.gem` file in  
extract mode, it derives a basename-based string and passes that  
filename-derived value into `rpmGetPath()` to build the `.gemspec` output  
name:
```c
} else if (at->compressed == COMPRESSED_GEM) {
char *tmp = xstrdup(fn);
const char *bn = basename(tmp);
size_t nvlen = strlen(bn) - 3;
char *gem = rpmGetPath("%{__gem}", NULL);
char *gemspec = NULL;
char gemnameversion[nvlen];
rstrlcpy(gemnameversion, bn, nvlen);
gemspec = rpmGetPath("", gemnameversion, ".gemspec", NULL);
rasprintf(&buf, "%s '%s' && %s spec '%s' --ruby > '%s'",
zipper, fn, gem, fn, gemspec);
```
`rpmGetPath()` concatenates its arguments and then calls `rpmExpand(dest,  
NULL)`. In the macro engine, `%(...)` is treated as a shell escape and  
reaches `doShellEscape()`, which executes the expanded command via  
`popen(buf, "r")`. Because `rpmuncompress` builds the command string before  
it checks `if (dryrun)`, a payload such as `foo%(touch  
/tmp/rpm_macro_poc).gem` executes during command construction, including  
under `rpmuncompress -n -x`.
This is directly reproducible through the helper CLI. Packaging or  
automation workflows may also be exposed if they invoke `rpmuncompress -x`  
on attacker-controlled `.gem` source filenames.
Steps to reproduce:
1. Build or use `rpmuncompress` from this package.
2. Create a file with a `.gem` suffix and a macro payload in its filename.  
In the reproduced case, 13 bytes of content were sufficient for detection  
to proceed:
```bash
printf '1234567890123' > 'foo%(touch /tmp/rpm_macro_poc).gem'
```
3. Run extraction in dry-run mode:
```bash
rpmuncompress -n -x 'foo%(touch /tmp/rpm_macro_poc).gem'
```
4. Verify the side effect:
```bash
ls -l /tmp/rpm_macro_poc
```
5. `/tmp/rpm_macro_poc` exists, showing that the `%()` payload executed  
while `rpmuncompress` was constructing the `.gemspec` path rather than  
during the later extraction stage.
Mitigation: Until a fix is shipped, do not invoke `rpmuncompress -x` on  
untrusted `.gem` filenames. Renaming the file to remove RPM macro syntax  
before extraction, or using an extractor that does not expand RPM macros in  
filename-derived strings, blocks the demonstrated path. In automated build  
environments, reject or sanitize untrusted source archive names before  
extraction.
Proposed Fix: Avoid passing filename-derived content through `rpmGetPath()`  
in the `.gem` branch. Plain string concatenation is sufficient for  
`.gemspec` construction and prevents macro evaluation of  
attacker-controlled basenames.
```diff
diff --git a/tools/rpmuncompress.c b/tools/rpmuncompress.c
@@ -106,7 +106,8 @@ static char *doUntar(const char *fn)
char gemnameversion[nvlen];
rstrlcpy(gemnameversion, bn, nvlen);
   gemspec = rpmGetPath("", gemnameversion, ".gemspec", NULL);
+    /* Avoid macro expansion on filename-derived input */
+    gemspec = rstrscat(NULL, gemnameversion, ".gemspec", NULL);
```


------
This report was generated using AI technology. Always review AI-generated  
content prior to use