{"record":{"id":"97c0951cfd1895e5","repo":"astrid-runtime/astrid","slug":"unsafe-capsule-archive-path","errorCode":null,"errorMessage":"unsafe capsule archive path '{}'","messagePattern":"unsafe capsule archive path '(.+?)'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-build/src/artifact.rs","lineNumber":297,"sourceCode":"        }\n        records.push(hash_reader(path, entry.size(), &mut entry)?);\n    }\n    Ok((records, envelope))\n}\n\nfn normalized_entry_path<R: Read>(entry: &tar::Entry<'_, R>) -> anyhow::Result<String> {\n    let path = entry.path().context(\"invalid capsule archive path\")?;\n    let mut parts = Vec::new();\n    for component in path.components() {\n        match component {\n            Component::Normal(part) => parts.push(\n                part.to_str()\n                    .context(\"capsule archive paths must be UTF-8\")?\n                    .to_string(),\n            ),\n            Component::CurDir => {},\n            Component::ParentDir | Component::RootDir | Component::Prefix(_) => {\n                bail!(\"unsafe capsule archive path '{}'\", path.display());\n            },\n        }\n    }\n    if parts.is_empty() {\n        bail!(\"capsule archive contains an empty path\");\n    }\n    Ok(parts.join(\"/\"))\n}\n\nfn hash_reader(path: String, size: u64, reader: &mut impl Read) -> anyhow::Result<ContentRecord> {\n    let mut hasher = blake3::Hasher::new();\n    let mut read = 0_u64;\n    let mut buffer = [0_u8; 16 * 1024];\n    loop {\n        let count = reader.read(&mut buffer)?;\n        if count == 0 {\n            break;\n        }","sourceCodeStart":279,"sourceCodeEnd":315,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-build/src/artifact.rs#L279-L315","documentation":"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.","triggerScenarios":"Thrown at crates/astrid-build/src/artifact.rs:297 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","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"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}