rust-lang/cargo · error

invalid tarball downloaded, contains a file at

Error message

invalid tarball downloaded, contains a file at {entry_path:?} which isn't under {prefix:?}

What it means

While unpacking a `.crate` tarball, Cargo requires every entry's path to be under the package prefix (`<pkg>-<ver>/`). If `entry_path.strip_prefix(prefix)` fails, the tarball contains a file outside the expected root — a path-traversal or malformed-tarball safety violation. Cargo blocks it to prevent overwriting other crates' source.

Solutions

  1. Re-download the official `.crate` from crates.io or the original registry to replace a corrupt/repackaged one.
  2. If you publish crates, ensure packaging uses `cargo package` which emits the correct root prefix.
  3. Clear cache: `rm ~/.cargo/registry/cache/<index>/<pkg>-<ver>.crate` and refetch.
  4. Audit the registry mirror — reject re-packaged tarballs lacking the `<pkg>-<ver>/` prefix.

Example fix

# before: tarball with flat (non-prefixed) layout
$ tar tf serde-1.0.0.crate
Cargo.toml
src/lib.rs

# after: properly packaged (re-fetch from trusted registry)
$ tar tf serde-1.0.0.crate
serde-1.0.0/Cargo.toml
serde-1.0.0/src/lib.rs
Defensive patterns

Strategy: validation

Validate before calling

fn validate_tarball_prefix(tar: &tar::Archive<std::fs::File>, expected_prefix: &str) -> Result<(), anyhow::Error> {
    for entry in tar.entries()? {
        let e = entry?;
        let p = e.path()?;
        if !p.starts_with(expected_prefix) {
            anyhow::bail!("entry outside prefix: {:?}", p);
        }
    }
    Ok(())
}

Type guard

fn tarball_all_under_prefix(path: &std::path::Path, prefix: &str) -> bool {
    let f = std::fs::File::open(path).ok();
    f.and_then(|f| tar::Archive::new(f).entries().ok()).map_or(false, |mut es| {
        es.by_ref().all(|e| e.map_or(false, |e| e.path().map_or(false, |p| p.starts_with(prefix))))
    })
}

Try / catch

if entry_path.strip_prefix(prefix).is_err() {
    // do not bail hard if you can re-fetch: replace the crate and retry
    refetch_crate(pkg)?;
    return unpack(...);
}

Prevention

When it happens

Trigger: `unpack()` iterates tar entries; an entry path does not start with the package prefix. Caused by a tarball built with absolute paths, `..` segments, or missing the `<pkg>-<ver>/` root — i.e. a non-conformant or malicious `.crate` file.

Common situations: A hand-built / third-party-packaged `.crate` that omits the conventional root directory; a tampered or corrupted tarball; an old or non-standard tool producing flat tarballs; a registry mirror that re-packaged crates incorrectly.

Related errors


AI-assisted analysis of rust-lang/cargo@98a09e7e7d (2026-08-11). Data as JSON: /api/errors/c0662a46180a7ac3. Report an issue: GitHub.

Appendix: source

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

    for entry in tar.entries()? {
        let mut entry = entry.context("failed to iterate over archive")?;
        let entry_path = entry
            .path()
            .context("failed to read entry path")?
            .into_owned();

        if let Ok(path) = entry_path.strip_prefix(prefix) {
            if !include(path) {
                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)
        {

View on GitHub (pinned to 98a09e7e7d)