astrid-runtime/astrid · critical
malicious shuttle detected: unsupported entry type for '{}'
Error message
malicious shuttle detected: unsupported entry type for '{}' (only regular files are allowed) What it means
After rejecting links, `unpack` requires every remaining entry to be a regular file. Device nodes, FIFOs, sockets, and other special tar entry types are rejected because a legitimate `.shuttle` only ever carries regular files — an exotic type signals corruption or an attack.
Source
Thrown at crates/astrid-cli/src/commands/distro/shuttle.rs:210
}
let et = entry.header().entry_type();
if et.is_symlink() || et.is_hard_link() {
bail!(
"malicious shuttle detected: links are not allowed ('{}')",
entry_path.display()
);
}
// Skip directory entries — parents are created as needed below.
if et.is_dir() {
continue;
}
// Everything that survives to here must be an ordinary file. Device
// nodes, FIFOs, sockets, and any other special entry type are
// rejected: a `.shuttle` only ever legitimately carries regular
// files, so an exotic type is either corruption or an attack.
if !et.is_file() {
bail!(
"malicious shuttle detected: unsupported entry type for '{}' \
(only regular files are allowed)",
entry_path.display()
);
}
// A corrupt/undecodable size field must fail closed, not be coerced
// to 0 — otherwise header corruption silently bypasses the cap.
let size = entry
.header()
.size()
.context("malicious shuttle detected: unreadable member size")?;
if size > MAX_MEMBER_BYTES {
bail!(
"shuttle member '{}' is {size} bytes, exceeding the {MAX_MEMBER_BYTES}-byte limit",
entry_path.display()
);
}View on GitHub (pinned to affd8760f4)
Solutions
- Discard the archive — it is either corrupt or malicious; re-download or re-pack from a trusted staged directory.
- Re-pack using the official `pack` flow, which only emits regular-file members.
- Ensure the staging directory contains no sockets/FIFOs (e.g. leftover Unix sockets from a dev server) before packing.
Example fix
// before staged/run/api.sock # leftover socket in staging dir // after $ rm staged/run/api.sock && astrid distro pack ...
Defensive patterns
Strategy: validation
Validate before calling
fn only_regular_files(types: &[String]) -> bool {
types.iter().all(|t| t == "file" || t == "dir")
} Try / catch
if let Err(e) = shuttle::unpack(archive, dest) {
if e.to_string().contains("unsupported entry type") {
eprintln!("archive has non-file entries; discard or repack: {e}");
}
} Prevention
- Remove sockets/FIFOs/device files from the staging directory before packing
- Use the official pack tooling, which only emits regular files
- Never unpack capsules from unverified producers
When it happens
Trigger: Calling `shuttle::unpack` on an archive containing a device node, FIFO, socket, or other non-regular/non-directory entry type (`!et.is_file()`), as covered by `unpack_rejects_non_regular_entry`.
Common situations: An archive crafted to smuggle device nodes, or produced by tooling that preserves special files; unpacking a truncated/mangled archive that misparses headers.
Understand the failure class
Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.
Related errors
- malicious shuttle detected: invalid path '{}'
- malicious shuttle detected: links are not allowed ('{}')
- capsule archive contains an unsafe path {}
- capsule archive contains a link or special file {name}
- durable capsule archive contains unsafe path
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/d8581040f8f1b730.
Report an issue: GitHub.