astrid-runtime/astrid · error
capsule cache path is redirected: {error}
Error message
capsule cache path is redirected: {error} What it means
Wraps `astrid_core::platform_fs::verify_no_redirects(dir)` failing: although the cache dir is under the registry cache root, it contains a symlink or redirect component that could escape the durable cache. The kernel refuses to trust the path.
Source
Thrown at crates/astrid-kernel/src/lib.rs:1586
)
.map_err(|error| anyhow::anyhow!("resolve durable capsule cache target: {error}"))
}
/// Validate the disposable cache path against an exact owner snapshot.
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
fn validate_published_cache_path(
&self,
dir: &Path,
principal: &PrincipalId,
manifest: &astrid_capsule_types::manifest::CapsuleManifest,
snapshot: &astrid_storage::CapsulePackageSnapshot,
) -> anyhow::Result<()> {
let cache_root = self.astrid_home.run_dir().join("capsules");
let relative = dir.strip_prefix(&cache_root).map_err(|_| {
anyhow::anyhow!("capsule cache path is outside the durable registry cache")
})?;
astrid_core::platform_fs::verify_no_redirects(dir)
.map_err(|error| anyhow::anyhow!("capsule cache path is redirected: {error}"))?;
let components: Vec<String> = relative
.components()
.map(|component| match component {
std::path::Component::Normal(value) => Ok(value.to_string_lossy().into_owned()),
_ => Err(anyhow::anyhow!(
"capsule cache path contains unsafe components"
)),
})
.collect::<anyhow::Result<_>>()?;
if components.len() != 3 {
anyhow::bail!("capsule cache path does not contain owner/id/digest components");
}
let uid = self
.principal_directory
.uid_for(principal)
.map_err(|error| anyhow::anyhow!("resolve capsule cache owner UID: {error}"))?;
if components[0] != uid.to_string() || components[1] != manifest.package.name {
anyhow::bail!("capsule cache owner or id does not match authenticated registry scope");View on GitHub (pinned to affd8760f4)
Solutions
- Replace the symlinked component inside run_dir/capsules with a real directory
- Purge the affected capsule cache directory and re-install/re-publish to repopulate it
- Extract capsule archives without preserving symlinks
- Audit how the cache was populated (backup restore, rsync -a, manual ln -s)
Example fix
// before ~/.astrid/run/capsules/1001/my-capsule/<digest> -> /mnt/shared/cache // after rm ~/.astrid/run/capsules/1001/my-capsule/<digest> mkdir -p ~/.astrid/run/capsules/1001/my-capsule/<digest> && # reinstall real files
Defensive patterns
Strategy: validation
Validate before calling
astrid_core::platform_fs::verify_no_redirects(dir)?; // pre-check before install
Type guard
fn has_no_symlinks(dir: &Path) -> bool {
dir.symlink_metadata().map(|m| !m.file_type().is_symlink()).unwrap_or(false)
&& std::fs::read_dir(dir).map(|rd| rd.filter_map(Result::ok).all(|e| has_no_symlinks(&e.path()))).unwrap_or(false)
} Prevention
- Extract archives with --no-same-owner and no symlink preservation
- Avoid symlinked shared storage for run_dir/capsules
- Audit restore/backup pipelines for symlink materialization
When it happens
Trigger: validate_published_cache_path finds a symlink anywhere inside the computed capsule cache directory tree (owner, id, or digest level) when validating an exact owner snapshot.
Common situations: Admin symlinked a capsule cache dir to shared storage or another disk; archive extraction created symlinks; restore/backup tooling materialized links; attacker-supplied archive with link entries.
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 materialization cache is redirected or not a directo
- cache contains a redirect or special entry: {}
- cache changed to a redirect or special entry: {}
- capsule projection contains a symbolic link: {}
- workspace capsule tree contains an unsafe redirect: {error}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/678cb6e6dea6465f.
Report an issue: GitHub.