{"id":"4986b5cef2b3f028","repo":"rust-lang/cargo","slug":"invalid-tarball-downloaded-contains-an-entry-at","errorCode":null,"errorMessage":"invalid tarball downloaded, contains an entry at {entry_path:?} with invalid type {t:?}","messagePattern":"invalid tarball downloaded, contains an entry at (.+?) with invalid type (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"critical","filePath":"src/sources/registry/mod.rs","lineNumber":997,"sourceCode":"                continue;\n            }\n        } else {\n            // We're going to unpack this tarball into the global source\n            // directory, but we want to make sure that it doesn't accidentally\n            // (or maliciously) overwrite source code from other crates. Cargo\n            // itself should never generate a tarball that hits this error, and\n            // crates.io should also block uploads with these sorts of tarballs,\n            // but be extra sure by adding a check here as well.\n            anyhow::bail!(\n                \"invalid tarball downloaded, contains \\\n                     a file at {entry_path:?} which isn't under {prefix:?}\",\n            )\n        }\n\n        // Prevent unpacking symlinks and other unexpected entry types\n        match entry.header().entry_type() {\n            EntryType::Regular | EntryType::Directory => {}\n            t => anyhow::bail!(\n                \"invalid tarball downloaded, contains an entry at {entry_path:?} with invalid type {t:?}\",\n            ),\n        }\n\n        // Prevent unpacking the lockfile from the crate itself.\n        if entry_path\n            .file_name()\n            .map_or(false, |p| p == PACKAGE_SOURCE_LOCK)\n        {\n            continue;\n        }\n        // Unpacking failed\n        bytes_written += entry.size();\n        let mut result = entry.unpack_in(parent).map_err(anyhow::Error::from);\n        if cfg!(windows) && restricted_names::is_windows_reserved_path(&entry_path) {\n            result = result.with_context(|| {\n                format!(\n                    \"`{}` appears to contain a reserved Windows path, \\","sourceCodeStart":979,"sourceCodeEnd":1015,"githubUrl":"https://github.com/rust-lang/cargo/blob/0e07a155371a6ce88ae53a2c00df940280c09a67/src/sources/registry/mod.rs#L979-L1015","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","solutions":["Clear the cached tarball (`~/.cargo/registry/cache/<reg>/<pkg>-<ver>.crate`) and refetch from a trusted source.","Re-package the crate with standard `cargo package` (which emits only regular files + dirs).","Inspect with `tar -tvf <file>.crate` to locate the offending entry, then fix the upstream packaging tool.","If the registry is untrusted, treat it as a supply-chain incident and stop consuming it."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Reject any tarball entry that isn't Regular or Directory.\nuse tar::EntryType;\nfn tarball_entries_safe<R: Read>(tar: &mut tar::Archive<R>) -> bool {\n    for e in tar.entries().ok().into_iter().flatten() {\n        let t = e.header().entry_type();\n        if t != EntryType::Regular && t != EntryType::Directory { return false; }\n    }\n    true\n}","typeGuard":"use tar::EntryType;\npub fn entry_type_allowed(t: EntryType) -> bool {\n    matches!(t, EntryType::Regular | EntryType::Directory)\n}","tryCatchPattern":null,"preventionTips":["Package crates with `cargo package` only — never custom tarball tooling that preserves symlinks.","Treat any symlink/hardlink/device entry in a `.crate` as a security incident.","Consume crates only from trusted registries."],"tags":["cargo","registry","tarball","security","symlink","validation"],"analyzedSha":"0e07a155371a6ce88ae53a2c00df940280c09a67","analyzedAt":"2026-08-06T01:46:58.334Z","schemaVersion":2}