CVE-2026-84233: Rpm: command execution via macro expansion in `rpmuncompress -x` for crafted `.gem` filenames
A flaw was found in rpm. A local attacker could supply a specially crafted .gem filename containing RPM macro syntax. When a user or automated workflow invokes rpmuncompress -x on this file, the macro expansion occurs during command construction. This allows the attacker to execute arbitrary commands with the privileges of the invoking account, leading to a compromise of confidentiality, integrity, and availability.
Other sources
AIONLYREPORT 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 == COMPRESSEDGEM) { char tmp = xstrdup(fn); const char bn = basename(tmp); sizet 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/rpmmacropoc).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/rpmmacropoc).gem' 3. Run extraction in dry-run mode: bash rpmuncompress -n -x 'foo%(touch /tmp/rpmmacropoc).gem' 4. Verify the side effect: bash ls -l /tmp/rpmmacropoc 5. /tmp/rpmmacropoc 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
— Red Hat
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Configuration
Until a fix is shipped, do not invoke `rpmuncompress -x` on attacker-controlled or untrusted `.gem` files (e.g., crafted basenames containing RPM macro syntax like `%(...)`). If possible, run in a mode that does not trigger the vulnerable expansion/extraction path (the advisory specifically notes the vulnerability occurs during command construction for `rpmuncompress -x`).
rpm tools/rpmuncompress (gem extraction path) rpmuncompress invocation = avoid -x on untrusted .gem basenames - Configuration
Before extracting an untrusted `.gem`, reject or sanitize its filename/basename to remove RPM macro syntax (e.g., rename inputs so they do not contain `%(...)`) so the attacker-controlled basename cannot reach the `.gemspec` construction path.
rpm tools/rpmuncompress (input handling) filename processing for .gemspec construction = reject or sanitize macro-syntax in untrusted archive names before extraction