astrid-runtime/astrid · critical
durable capsule archive contains unsafe path
Error message
durable capsule archive contains unsafe path
What it means
While inventorying the tar archive, read_archive_files encountered an entry whose path is absolute or contains a ParentDir (..) or RootDir component. This is a path-traversal guard: such entries could escape the intended extraction root, so the library refuses to process the archive at all.
Source
Thrown at crates/astrid-capsule-install/src/storage.rs:372
}
fn read_archive_files(archive_bytes: &[u8]) -> anyhow::Result<ArchiveInventory> {
let decoder = flate2::read::GzDecoder::new(Cursor::new(archive_bytes));
let mut archive = tar::Archive::new(decoder);
let mut files = std::collections::BTreeMap::new();
let mut directories = std::collections::BTreeSet::new();
for entry in archive.entries().context("read durable capsule archive")? {
let mut entry = entry.context("read durable capsule archive entry")?;
let path = entry.path().context("read durable capsule archive path")?;
if path.is_absolute()
|| path.components().any(|component| {
matches!(
component,
std::path::Component::ParentDir | std::path::Component::RootDir
)
})
{
bail!("durable capsule archive contains unsafe path");
}
let entry_type = entry.header().entry_type();
if !entry_type.is_dir() && !entry_type.is_file() {
bail!("durable capsule archive contains a link or special file");
}
let name = path
.to_str()
.ok_or_else(|| anyhow::anyhow!("durable capsule archive path is not UTF-8"))?
.replace('\\', "/");
if files.contains_key(&name) || directories.contains(&name) {
bail!("durable capsule archive contains duplicate path {name}");
}
if entry_type.is_dir() {
if !directories.insert(name) {
bail!("durable capsule archive contains duplicate directory path");
}View on GitHub (pinned to affd8760f4)
Solutions
- Rebuild the archive with relative, traversal-free paths (strip leading '/' and '..' components at creation).
- Reject or quarantine the offending archive; do not attempt to sanitize it silently.
- Audit the archive-generation tooling for absolute-path leakage.
- Verify archive provenance/manifest digest to detect tampering before reading.
Example fix
// before: archiving with an absolute path let name = entry_path.to_string_lossy(); // "/abs/dir/file" // after: make the path relative before writing to the tar let name = entry_path.strip_prefix(source_dir)?.to_string_lossy().to_string();
Defensive patterns
Strategy: validation
Validate before calling
fn entry_path_is_safe(p: &std::path::Path) -> bool {
!p.is_absolute()
&& !p.components().any(|c| matches!(
c,
std::path::Component::ParentDir | std::path::Component::RootDir
))
} Type guard
fn is_relative_safe(p: &std::path::Path) -> bool {
p.is_relative() && p.components().all(|c| matches!(c, std::path::Component::Normal(_)))
} Try / catch
match read_verified_durable_package_for_owner(&store, owner, id).await {
Ok(pkg) => pkg,
Err(e) if e.to_string().contains("unsafe path") => {
// reject/quarantine the archive; rebuild with relative paths
},
Err(e) => return Err(e),
} Prevention
- Always strip the source-dir prefix so tar entries are relative.
- Scan archives with tar -tf or a library check for absolute/'..' paths before publishing.
- Never accept capsule archives from untrusted sources without the manifest digest check.
When it happens
Trigger: read_archive_files (via read_verified_durable_package_for_owner) on a tar.gz containing entries like "/etc/passwd", "../../escape", or paths with leading root components.
Common situations: Building the tar on Windows or with scripts that emit absolute paths; malicious or tampered archives; archiving with tools that preserve leading slashes; hand-crafted tar files in tests.
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
- capsule archive contains an unsafe path {}
- capsule archive contains a link or special file {name}
- durable capsule archive contains a link or special file
- malicious shuttle detected: invalid path '{}'
- symlink {} resolves outside the capsule source root ({}); re
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/dbeb324b49cc04df.
Report an issue: GitHub.