{"record":{"id":"6d9c7ef1add4ca03","repo":"astrid-runtime/astrid","slug":"unsafe-capsule-path","errorCode":null,"errorMessage":"unsafe capsule path '{}'","messagePattern":"unsafe capsule path '(.+?)'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-build/src/artifact.rs","lineNumber":522,"sourceCode":"        let mut file = File::open(&path)?;\n        let size = file.metadata()?.len();\n        records.push(hash_reader(normalized, size, &mut file)?);\n    }\n    Ok(())\n}\n\nfn normalize_relative_path(path: &Path) -> anyhow::Result<String> {\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 paths must be UTF-8\")?\n                    .to_string(),\n            ),\n            Component::CurDir => {},\n            Component::ParentDir | Component::RootDir | Component::Prefix(_) => {\n                bail!(\"unsafe capsule path '{}'\", path.display());\n            },\n        }\n    }\n    Ok(parts.join(\"/\"))\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[cfg(windows)]\n    struct FreshWindowsHome {\n        path: std::path::PathBuf,\n    }\n\n    #[cfg(windows)]\n    impl FreshWindowsHome {\n        fn new() -> Self {","sourceCodeStart":504,"sourceCodeEnd":540,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-build/src/artifact.rs#L504-L540","documentation":"Fired by normalize_relative_path when a relative path within a capsule content tree contains a non-Normal component (ParentDir, RootDir, or Prefix), i.e. it would escape or be absolute. Generic path-safety guard over user-supplied tree paths.","triggerScenarios":"Thrown at crates/astrid-build/src/artifact.rs:522 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Fix the content tree so all paths are relative and stay under the capsule root","Remove symlinks or `..` references from the content directory","Rebuild the capsule"],"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"}