astrid-runtime/astrid · error
workspace capsule tree contains an unsafe redirect: {error}
Error message
workspace capsule tree contains an unsafe redirect: {error} What it means
Wraps a failure from `verify_tree` when checking that a directory inside the workspace state dir contains no symlinks or path components that redirect outside the tree. The kernel refuses to traverse a capsule tree that could be a symlink-escape vector. It is a security guard, not a functional bug.
Source
Thrown at crates/astrid-kernel/src/lib.rs:1446
.with_identity_store(Arc::clone(&kernel.identity_store))
.with_access_resolver(access_resolver);
drop(astrid_runtime::spawn(dispatcher.run()));
debug_assert_eq!(
kernel.event_bus.subscriber_count(),
INTERNAL_SUBSCRIBER_COUNT,
"INTERNAL_SUBSCRIBER_COUNT is stale; update it when adding permanent subscribers"
);
Ok(kernel)
}
fn verify_workspace_capsule_tree(&self, dir: &Path) -> anyhow::Result<()> {
if let Ok(relative) = dir.strip_prefix(self.workspace_selection.state_dir()) {
self.workspace_selection
.verify_tree(relative)
.map_err(|error| {
anyhow::anyhow!("workspace capsule tree contains an unsafe redirect: {error}")
})?;
}
Ok(())
}
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
fn verify_workspace_component_paths(
&self,
dir: &Path,
manifest: &astrid_capsule_types::manifest::CapsuleManifest,
) -> anyhow::Result<()> {
let Ok(capsule_relative) = dir.strip_prefix(self.workspace_selection.state_dir()) else {
return Ok(());
};
for component in &manifest.components {
if component.path.is_absolute() {
anyhow::bail!(
"workspace capsule component must be relative: {}",View on GitHub (pinned to affd8760f4)
Solutions
- Find the offending entry reported by the inner error and replace the symlink with a real file/directory
- Re-extract or reinstall the capsule archive with symlink preservation disabled (e.g. tar --no-same-owner without -h)
- Remove the stale capsule directory under the workspace state dir and let the kernel re-materialize it
- Inspect verify_tree in astrid-kernel to confirm which path component failed before deleting data
Example fix
// before: capsule tree contains symlink state_dir/capsules/foo -> /etc/something // after rm state_dir/capsules/foo && mkdir state_dir/capsules/foo && # re-extract real files into it
Defensive patterns
Strategy: validation
Validate before calling
let rel = dir.strip_prefix(workspace_selection.state_dir())?;
if let Err(e) = workspace_selection.verify_tree(rel) {
// reject before handing to kernel
return Err(e);
} Type guard
fn is_under_state_dir(dir: &Path, state_dir: &Path) -> bool {
dir.strip_prefix(state_dir).is_ok()
} Prevention
- Extract capsule archives with symlink preservation disabled
- Never hand-create symlinks inside the workspace state dir
- Use workspace tooling (not manual copies) to populate capsule trees
When it happens
Trigger: Calling workspace capsule verification (verify_workspace_capsule_tree) when `dir` sits under workspace_selection.state_dir() and verify_tree finds a symlink or redirect component inside the relative tree.
Common situations: A capsule was extracted with symlinks preserved from an archive; a user hand-linked cache/state directories to another disk; a previous partial install left dangling links; shared state dirs synced via tools that materialize symlinks.
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 projection contains a symbolic link: {}
- leftover capsule authority receipt is not a regular file: {}
- legacy capsule authority root is not a regular directory: {}
- legacy capsule authority root contains a non-regular entry:
- legacy capsule authority root is not a regular directory: {}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/85c90d00759d5077.
Report an issue: GitHub.