astrid-runtime/astrid · error
unsafe capsule archive path
Error message
unsafe capsule archive path '{}' What it means
Fired by normalized_entry_path when a tar entry path in a capsule archive contains a non-Normal component (parent dir, root, or prefix), i.e. the path escapes or is absolute. Guarding against path-traversal entries in untrusted capsule archives.
Solutions
- Repack the capsule archive so all entry paths are plain relative, UTF-8 paths
- Inspect the archive with `tar -tf` and remove entries containing `..`, leading `/`, or drive prefixes
- Obtain a freshly built capsule from the publisher
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at crates/astrid-build/src/artifact.rs:297 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/97c0951cfd1895e5.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-build/src/artifact.rs:297
}
records.push(hash_reader(path, entry.size(), &mut entry)?);
}
Ok((records, envelope))
}
fn normalized_entry_path<R: Read>(entry: &tar::Entry<'_, R>) -> anyhow::Result<String> {
let path = entry.path().context("invalid capsule archive path")?;
let mut parts = Vec::new();
for component in path.components() {
match component {
Component::Normal(part) => parts.push(
part.to_str()
.context("capsule archive paths must be UTF-8")?
.to_string(),
),
Component::CurDir => {},
Component::ParentDir | Component::RootDir | Component::Prefix(_) => {
bail!("unsafe capsule archive path '{}'", path.display());
},
}
}
if parts.is_empty() {
bail!("capsule archive contains an empty path");
}
Ok(parts.join("/"))
}
fn hash_reader(path: String, size: u64, reader: &mut impl Read) -> anyhow::Result<ContentRecord> {
let mut hasher = blake3::Hasher::new();
let mut read = 0_u64;
let mut buffer = [0_u8; 16 * 1024];
loop {
let count = reader.read(&mut buffer)?;
if count == 0 {
break;
}View on GitHub (pinned to affd8760f4)