astrid-runtime/astrid · error
authenticated AstridFS.app is redirected or not a directory
Error message
authenticated AstridFS.app is redirected or not a directory
What it means
prepare_macos_update_assets validates the contents of an authenticated (signed, verified) macOS update archive before installing. It requires AstridFS.app inside the extract directory to be a real directory, not a symlink or other redirected entry. This guards against symlink-based path redirection attacks sneaking into the privileged update path.
Source
Thrown at crates/astrid-cli/src/commands/self_update/mod.rs:400
/// as temp files in `install_dir` (same filesystem) and `rename`d into place —
/// atomic per file on Unix. Windows stages and flushes bytes on the live volume,
/// then uses a recovery journal around handle-relative
/// `SetFileInformationByHandle(FileRenameInfo)` transitions, each atomic at the
/// individual name boundary; an interrupted mixed set is restored on the next
/// attempt. The `.bak` copies are left in place for manual rollback after a
/// successful update.
fn backup_and_swap(install_dir: &Path, extract_dir: &Path, names: &[&str]) -> anyhow::Result<()> {
astrid_core::platform_fs::replace_executable_set(install_dir, extract_dir, names)
.context("failed to replace authenticated Astrid executables")
}
fn prepare_macos_update_assets(extract_dir: &Path, target: &str) -> anyhow::Result<()> {
if !target.contains("-apple-darwin") {
return Ok(());
}
let app = extract_dir.join("AstridFS.app");
let app_metadata = std::fs::symlink_metadata(&app)
.with_context(|| format!("authenticated macOS release is missing {}", app.display()))?;
anyhow::ensure!(
app_metadata.is_dir() && !app_metadata.file_type().is_symlink(),
"authenticated AstridFS.app is redirected or not a directory"
);
for name in ["manage-macos-fskit.sh", "validate-macos-fskit.sh"] {
let source = extract_dir.join("macos").join(name);
let metadata = std::fs::symlink_metadata(&source).with_context(|| {
format!(
"authenticated macOS release is missing {}",
source.display()
)
})?;
anyhow::ensure!(
metadata.is_file() && !metadata.file_type().is_symlink(),
"authenticated macOS lifecycle tool is redirected or not regular: {name}"
);
std::fs::copy(&source, extract_dir.join(name))?;
}
Ok(())View on GitHub (pinned to affd8760f4)
Solutions
- Re-download the release from the official channel so a verified, untampered archive is used
- Inspect the archive (tar -tvf) and confirm AstridFS.app is a real directory
- Fix the packaging script that produced a symlinked AstridFS.app
- Re-run the update after removing any stale extraction directory
Defensive patterns
Strategy: validation
Validate before calling
fn is_real_dir(p: &Path) -> bool {
std::fs::symlink_metadata(p).map(|m| m.is_dir() && !m.file_type().is_symlink()).unwrap_or(false)
}
assert!(is_real_dir(&extract_dir.join("AstridFS.app"))); Type guard
fn is_real_dir(p: &Path) -> bool {
std::fs::symlink_metadata(p)
.map(|m| m.is_dir() && !m.file_type().is_symlink())
.unwrap_or(false)
} Prevention
- Only install from official signed release archives
- Inspect archive contents (tar -tvf) for symlinks before extracting
- Reject any archive packaging that symlinks app bundles
- Re-extract to a clean directory on failure
When it happens
Trigger: apply_authenticated_update processes a -apple-darwin release archive whose extracted AstridFS.app is missing its directory nature: it is a symlink, a regular file, or otherwise not a plain directory per symlink_metadata.
Common situations: A tampered or repackaged release archive; a build/packaging script that accidentally symlinks AstridFS.app; extracting the archive in a way that converted entries into 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.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- authenticated macOS lifecycle tool is redirected or not regu
- capsule archive contains a link or special file {name}
- durable capsule archive contains a link or special file
- malicious shuttle detected: links are not allowed ('{}')
- leftover capsule authority receipt is not a regular file: {}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/813b4af88f7f88b4.
Report an issue: GitHub.