rust-lang/cargo · critical · anyhow::Error

invalid tarball downloaded, contains an entry at {entry_path

Error message

invalid tarball downloaded, contains an entry at {entry_path:?} with invalid type {t:?}

What it means

Companion guard to 177 (src/sources/registry/mod.rs:995): after the prefix check, Cargo inspects each tarball entry's `EntryType` and only allows `Regular` files and `Directory` entries. Anything else — symlinks, hardlinks, character/block devices, FIFOs — is rejected with `{t:?}` showing the offending type. This prevents tarballs from planting symlinks that could escape the unpack directory or target other files (a known supply-chain vector).

Source

Thrown at src/sources/registry/mod.rs:997

                continue;
            }
        } else {
            // We're going to unpack this tarball into the global source
            // directory, but we want to make sure that it doesn't accidentally
            // (or maliciously) overwrite source code from other crates. Cargo
            // itself should never generate a tarball that hits this error, and
            // crates.io should also block uploads with these sorts of tarballs,
            // but be extra sure by adding a check here as well.
            anyhow::bail!(
                "invalid tarball downloaded, contains \
                     a file at {entry_path:?} which isn't under {prefix:?}",
            )
        }

        // Prevent unpacking symlinks and other unexpected entry types
        match entry.header().entry_type() {
            EntryType::Regular | EntryType::Directory => {}
            t => anyhow::bail!(
                "invalid tarball downloaded, contains an entry at {entry_path:?} with invalid type {t:?}",
            ),
        }

        // Prevent unpacking the lockfile from the crate itself.
        if entry_path
            .file_name()
            .map_or(false, |p| p == PACKAGE_SOURCE_LOCK)
        {
            continue;
        }
        // Unpacking failed
        bytes_written += entry.size();
        let mut result = entry.unpack_in(parent).map_err(anyhow::Error::from);
        if cfg!(windows) && restricted_names::is_windows_reserved_path(&entry_path) {
            result = result.with_context(|| {
                format!(
                    "`{}` appears to contain a reserved Windows path, \

View on GitHub (pinned to 0e07a15537)

Solutions

  1. Clear the cached tarball (`~/.cargo/registry/cache/<reg>/<pkg>-<ver>.crate`) and refetch from a trusted source.
  2. Re-package the crate with standard `cargo package` (which emits only regular files + dirs).
  3. Inspect with `tar -tvf <file>.crate` to locate the offending entry, then fix the upstream packaging tool.
  4. If the registry is untrusted, treat it as a supply-chain incident and stop consuming it.
Defensive patterns

Strategy: validation

Validate before calling

// Reject any tarball entry that isn't Regular or Directory.
use tar::EntryType;
fn tarball_entries_safe<R: Read>(tar: &mut tar::Archive<R>) -> bool {
    for e in tar.entries().ok().into_iter().flatten() {
        let t = e.header().entry_type();
        if t != EntryType::Regular && t != EntryType::Directory { return false; }
    }
    true
}

Type guard

use tar::EntryType;
pub fn entry_type_allowed(t: EntryType) -> bool {
    matches!(t, EntryType::Regular | EntryType::Directory)
}

Prevention

When it happens

Trigger: A `.crate` archive containing a symlink, hardlink, or device/FIFO entry. Standard `cargo package` output never produces these, so encountering one implies a non-standard packaging tool, corruption, or a deliberately malicious tarball.

Common situations: A custom packaging pipeline that preserves symlinks; an attacker crafting a tarball with a symlink to overwrite files outside the crate dir; a corrupted re-packaging that turned a regular file into a link entry.

Related errors


AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06). Data as JSON: /data/errors/4986b5cef2b3f028.json. Report an issue: GitHub.