astrid-runtime/astrid · error
mountpoint contains traversal: {}
Error message
mountpoint contains traversal: {} What it means
validate_mountpoint_layout detects ParentDir (..) or CurDir (.) components in the mountpoint and bails with the full offending path. Traversal components make the effective mount target depend on the process working directory and can be abused to redirect the mount outside the intended directory, so they are rejected outright.
Source
Thrown at crates/astrid-storage-provider-fskit/src/main.rs:535
}
#[cfg(not(unix))]
fn validate_mountpoint_ancestors(mountpoint: &Path) -> Result<()> {
let _ = mountpoint;
Ok(())
}
fn validate_mountpoint_layout(mountpoint: &Path) -> Result<()> {
if !mountpoint.is_absolute() {
bail!("mountpoint must be absolute");
}
if mountpoint.components().any(|component| {
matches!(
component,
std::path::Component::ParentDir | std::path::Component::CurDir
)
}) {
bail!("mountpoint contains traversal: {}", mountpoint.display());
}
if mountpoint.parent().is_none() {
bail!("mountpoint must be below a parent directory");
}
Ok(())
}
#[cfg(target_os = "macos")]
pub(crate) async fn native_mount(lease: &StorageMountLeaseV1, mountpoint: &Path) -> Result<()> {
let output = tokio::process::Command::new("/sbin/mount")
.arg("-t")
.arg("astridfs")
.arg(&lease.resource_path)
.arg(mountpoint)
.output()
.await
.context("invoke macOS FSKit mount")?;
if !output.status.success() {View on GitHub (pinned to affd8760f4)
Solutions
- Remove ".." and "." components; express the mountpoint as a clean absolute path
- Canonicalize the path before passing it: std::fs::canonicalize (existing path) or lexical normalization
- Validate/reject the user input upstream before constructing the mountpoint
Example fix
// before
let mountpoint = PathBuf::from("/Volumes/./fskit/../fskit-mnt");
// after
let mountpoint = PathBuf::from("/Volumes/fskit-mnt"); Defensive patterns
Strategy: validation
Validate before calling
fn ensure_no_traversal(mp: &std::path::Path) -> anyhow::Result<()> {
let bad = mp.components().any(|c| matches!(c, std::path::Component::ParentDir | std::path::Component::CurDir));
anyhow::ensure!(!bad, "mountpoint contains traversal: {}", mp.display());
Ok(())
} Type guard
fn is_clean_path(p: &std::path::Path) -> bool {
!p.components().any(|c| matches!(c, std::path::Component::ParentDir | std::path::Component::CurDir))
} Prevention
- Normalize paths with canonicalize or lexical cleanup before use
- Sanitize user-supplied path components (reject ".." and ".")
- Use Path APIs, never string concatenation, for paths
When it happens
Trigger: Passing paths like /Volumes/../etc/mnt or ./mnt/fs to mount/unmount or any of the validate_* entry points.
Common situations: Concatenating strings instead of using PathBuf; user-supplied mount names containing ".."; normalizing with naive string joins rather than Path APIs.
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
- mountpoint ancestor is writable without sticky protection: {
- capsule projection escaped its root: {}
- private directory contains traversal: {}
- workspace tree contains a redirected or special entry: {}
- legacy audit tree contains a redirect or boundary: {}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/250df79abb865d7b.
Report an issue: GitHub.