tar-rs is a tar archive reading/writing library for Rust. In versions 0.4.44 and below, when unpacking a tar archive, the tar crate's…
GitHub_M·CWE-61·Published 2026-03-20
tar-rs is a tar archive reading/writing library for Rust. In versions 0.4.44 and below, when unpacking a tar archive, the tar crate's unpack_dir function uses fs::metadata() to check whether a path that already exists is a directory. Because fs::metadata() follows symbolic links, a crafted tarball containing a symlink entry followed by a directory entry with the same name causes the crate to treat the symlink target as a valid existing directory — and subsequently apply chmod to it. This allows an attacker to modify the permissions of arbitrary directories outside the extraction root. This issue has been fixed in version 0.4.45.
tar-rs is a tar archive reading/writing library for Rust. In versions 0.4.44 and below, when unpacking a tar archive, the tar crate's unpack_dir function uses fs::metadata() to check whether a path that already exists is a directory. Because fs::metadata() follows symbolic links, a crafted tarball containing a symlink entry followed by a directory entry with the same name causes the crate to treat the symlink target as a valid existing directory — and subsequently apply chmod to it. This allows an attacker to modify the permissions of arbitrary directories outside the extraction root. This issue has been fixed in version 0.4.45.
In versions 0.4.44 and below of tar-rs, when unpacking a tar archive, the tar crate's `unpack_dir` function uses [`fs::metadata()`][fs-metadata] to check whether a path that already exists is a directory. Because `fs::metadata()` follows symbolic links, a crafted tarball containing a symlink entry followed by a directory entry with the same name causes the crate to treat the symlink target as a valid existing directory — and subsequently apply chmod to it. This allows an attacker to modify the permissions of arbitrary directories outside the extraction root. This issue has been fixed in version 0.4.45. [fs-metadata]: https://doc.rust-lang.org/std/fs/fn.metadata.html
## Summary When unpacking a tar archive, the `tar` crate's `unpack_dir` function uses `fs::metadata()` to check whether a path that already exists is a directory. Because `fs::metadata()` follows symbolic links, a crafted tarball containing a symlink entry followed by a directory entry with the same name causes the crate to treat the symlink target as a valid existing directory — and subsequently apply `chmod` to it. This allows an attacker to modify the permissions of arbitrary directories outside the extraction root. ## Reproducer A malicious tarball contains two entries: (1) a symlink `foo` pointing to an arbitrary external directory, and (2) a directory entry `foo/.` (or just `foo`). When unpacked, `create_dir("foo")` fails with `EEXIST` because the symlink is already on disk. The `fs::metadata()` check then follows the symlink, sees a directory at the target, and allows processing to continue. The directory entry's mode bits are then applied via `chmod`, which also follows the symlink — modifying the permissions of the external target directory. ## Fix The fix is very simple, we now use `fs::symlink_metadata()` in `unpack_dir`, so symlinks are detected and rejected rather than followed. ## Credit This issue was reported by @xokdvium - thank you!
tar-rs es una biblioteca de lectura/escritura de archivos tar para Rust. En las versiones 0.4.44 e inferiores, al desempaquetar un archivo tar, la función `unpack_dir` del crate `tar` utiliza `fs::metadata()` para verificar si una ruta que ya existe es un directorio. Debido a que `fs::metadata()` sigue los enlaces simbólicos, un tarball manipulado que contiene una entrada de enlace simbólico seguida de una entrada de directorio con el mismo nombre hace que el crate trate el destino del enlace simbólico como un directorio existente válido y, posteriormente, le aplique `chmod`. Esto permite a un atacante modificar los permisos de directorios arbitrarios fuera de la raíz de extracción. Este problema ha sido solucionado en la versión 0.4.45.
| Version | Type | Source | Base | Exp | Impact | Vector |
|---|---|---|---|---|---|---|
| 3.1 | Primary | NVD | 6.5 | 2.8 | 3.6 | CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N |
| 3.1 | Secondary | GHSA | 6.5 | — | — | CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N |
| 4.0 | Primary | cve.org | 5.1 | — | — | CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N |
| 4.0 | Primary | cve.org | 5.1 | — | — | CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N |
| 4.0 | Secondary | NVD | 5.1 | — | — | CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X |
| 4.0 | Secondary | GHSA | 5.1 | — | — | CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N |