high
CVE
CVE-2026-25707
CWE
CWE-22
Affected Surface
`libzypp` before 17.38.10 and downstream distro builds that still ship the vulnerable parser behavior, openSUSE and SUSE systems that consume repositories through `zypper`, YaST, or other `libzypp`-based automation, Build systems, image pipelines, or Linux hosts that refresh or mirror less-trusted package repositories and process attacker-controlled `repomd.xml` or SuSE tags metadata
CVE-2026-25707 is a Linux package-management bug, but it belongs on an AppSec radar because it turns repository metadata into a local file-placement primitive. If your threat model still treats package metadata as “just download bookkeeping,” this disclosure is the counterexample: the parser trusted relative locations deeply enough that a hostile repository could try to mirror files outside the intended cache root.
The affected component is libzypp, the package-management library behind tools such as zypper and adjacent SUSE / openSUSE package workflows. In practice that means the issue can reach both developer-facing hosts and automation systems that refresh or mirror repositories inside build, image, or update pipelines.
Affected components and fixed versions
Public advisories agree on the core upstream version boundary:
libzyppbefore17.38.10is affected
The distro packaging details matter as well:
- openSUSE Tumbleweed fixed the issue in
17.38.10-1.1 - SUSE Linux Micro 6.1 received fixed
libzypppackages in the17.38.11line - later package sets such as the Leap 16 /
zypperbundle updates carry the fix in17.38.13
Operationally, the higher-level question is simpler than the distro matrix: if a host processed untrusted repository metadata with a vulnerable libzypp, the repository itself became a path-traversal input source.
The bug is visible in the repository metadata format
The upstream fix adds a test case that captures the entire problem in one line:
<data type="hostile">
<location href="../hostile/to_be_discarded"/>
</data>
That ../ is the heart of the issue. The parser was willing to consume repository metadata entries whose target location normalized outside the repository’s local cache area. In other words, repository refresh was not only deciding what to download, but also where on disk the mirrored object should land.
For application security teams, this is the important boundary:
attacker controls repository metadata
-> parser accepts relative traversal in <location href=...>
-> mirror path escapes repo-local cache directory
-> local file overwrite / DoS / privilege-escalation conditions become possible
That is why the issue reads more like a local-file-write primitive than a routine package-index parser bug.
Two parser paths needed hardening
The patch is especially useful because it shows the bug was not fixed with a generic “sanitize everything somewhere else” layer. The maintainers hardened the actual metadata readers that turn repository documents into download locations.
1. repomd.xml / YUM metadata path rejection
In RepomdFileReader.cc, the fix now rejects hostile href values before they become an OnMediaLocation:
Pathname location { reader_r->getAttribute("href").asString() };
if ( location.relativeDotDot() ) {
JobReport::warning(
str::sconcat(
_repomdFile, ": data type ", _typeStr,
": hostile location ", location,
" => discard data entry"
)
);
_discardDataEntry = true;
return true;
}
_location.setLocation( std::move(location), 1 );
That is the critical change. Before the fix, the parser would accept the location and carry on. After the fix, entries that normalize outside the repository root are explicitly discarded.
2. SuSE tags metadata path sanitization
The same commit also hardens ContentFileReader.cc, which processes SuSE tags content metadata. The new helper rejects entries containing relative traversal:
std::string sanitizeEntry( Pathname path_r )
{
if ( path_r.relativeDotDot() ) {
JobReport::warning(
str::sconcat(
"Content file: hostile location ",
path_r,
" => discard data entry"
)
);
return {};
}
return path_r.asString().substr( path_r.absolute() ? 1 : 2 );
}
It also normalizes top-level directories such as DESCRDIR and DATADIR through a related sanitizer:
Pathname sanitize( Pathname path_r )
{
Pathname ret = path_r.absolutename();
if ( path_r.relativeDotDot() ) {
JobReport::warning(
str::sconcat(
"Content file: hostile location ",
path_r,
" => ",
ret
)
);
}
return ret;
}
From an AppSec perspective, that dual hardening matters because it tells you the vulnerable surface was not a single helper function or one packaging format. Multiple metadata readers needed to stop trusting relative path segments from repository content.
Why this matters beyond desktop package management
libzypp often runs in contexts that are more sensitive than an ordinary laptop package refresh:
- golden-image or appliance build pipelines
- internal mirrors or staged repositories
- update services for edge, kiosk, or embedded Linux fleets
- CI environments that bootstrap build roots or test images from repos
- developer workstations with privileged package-management helpers
In each of those cases, “repository metadata controls where files are mirrored” is a meaningful security boundary. If the repository is hostile or compromised, the package manager can become an unexpected filesystem write path.
That is why the NVD language about denial of service or privilege escalation is credible. The exact outcome depends on where the mirrored path lands and what later code or permissions do with it, but the primitive itself is already dangerous.
Scoping and detection
First, identify whether the host is still on a vulnerable package line:
rpm -q libzypp zypper
zypper --version
Then review repository usage and cache contents:
zypper lr -u
rg -n '<location href="\\.\\./|<location href="[^"]*/\\.\\./' /var/cache/zypp /var/cache/zypp/raw
rg -n '(^|[[:space:]])\\.\\./' /var/cache/zypp/raw
The exact paths vary by distro release and repository type, but the review objective is consistent:
- Which repositories were configured during the exposure window?
- Were any of them third-party, staging, internal, unsigned, or unexpectedly changed?
- Did cached metadata or mirrors contain
../-style locations?
If you operate internal mirrors, also review pipeline logs or mirror jobs that ingest external metadata before republishing to downstream hosts. A hostile upstream repository can turn a mirror stage into the first place the traversal executes.
Remediation
Patch first:
- Upgrade
libzyppto a fixed build for your distro line. - Upgrade
zypperand related package-management components if your vendor bundles the fix in a coordinated update. - Refresh repository metadata after patching.
Then clean up the trust boundary:
- Remove or disable repositories you do not explicitly trust.
- Clear cached metadata from suspicious repositories and re-sync from known-good sources.
- Review local filesystem changes if a host consumed third-party or compromised repos during the vulnerable window.
- Prefer signed, vendor-controlled, and provenance-reviewed repositories for automation.
If you have evidence that a hostile repository was actually used, do not stop at package upgrades. Review the host like a local file-write incident, especially if the system had privileged update workflows or post-refresh automation that could have acted on overwritten files.
What defenders should remember
The most useful lesson from CVE-2026-25707 is architectural: repository metadata is executable control data for a package manager, even when it does not look like code. In vulnerable libzypp versions, that control data reached file-placement decisions strongly enough that ../ in metadata became security-relevant.
For AppSec and platform teams, this is the kind of Linux package vulnerability that deserves more attention than its parser-centric label suggests. If your software supply chain includes repository mirroring, custom repos, build-root refreshes, or automated zypper flows, a repo metadata traversal is not just a distro issue. It is part of your application delivery trust chain.