astrid-runtime/astrid · error
mountpoint ancestor is writable without sticky protection: {
Error message
mountpoint ancestor is writable without sticky protection: {} What it means
This error is raised by validate_mountpoint_ancestors when walking up every ancestor directory of a mountpoint and finding a directory that is group/other-writable (mode & 0o022 != 0) without the sticky bit set (mode & 0o1000 == 0). Such a directory lets any local user swap or replace the mountpoint path, enabling a symlink/mount-target attack, so the FSKit provider refuses to mount or unmount through it. It is a local-security hardening check, not a functional failure.
Source
Thrown at crates/astrid-storage-provider-fskit/src/main.rs:509
bail!(
"macOS did not activate an astridfs mount at {}",
mountpoint.display()
);
}
Ok(())
}
#[cfg(unix)]
fn validate_mountpoint_ancestors(mountpoint: &Path) -> Result<()> {
use std::os::unix::fs::MetadataExt as _;
let mut ancestor = mountpoint.parent();
while let Some(path) = ancestor {
let metadata = std::fs::symlink_metadata(path)
.with_context(|| format!("inspect mountpoint ancestor {}", path.display()))?;
let mode = metadata.mode();
if mode & 0o022 != 0 && mode & 0o1000 == 0 {
bail!(
"mountpoint ancestor is writable without sticky protection: {}",
path.display()
);
}
ancestor = path.parent();
}
Ok(())
}
#[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");View on GitHub (pinned to affd8760f4)
Solutions
- Move the mountpoint under a root-owned, non-world-writable directory such as /Volumes or /mnt
- Set the sticky bit on the ancestor: chmod +t /path/to/ancestor
- Tighten the ancestor permissions: chmod o-w,g-w /path/to/ancestor
- Verify with ls -ld each ancestor of the mountpoint until none are world-writable without +t
Example fix
// before (ancestor /srv/scratch is 0777) mountpoint = /srv/scratch/fs/mnt // after sudo chmod 0755 /srv/scratch # or chmod +t /srv/scratch mountpoint = /srv/scratch/fs/mnt
Defensive patterns
Strategy: validation
Validate before calling
fn mountpoint_ancestors_are_safe(mp: &std::path::Path) -> std::io::Result<()> {
let mut ancestor = mp.parent();
while let Some(path) = ancestor {
let mode = std::fs::symlink_metadata(path)?.mode();
if mode & 0o022 != 0 && mode & 0o1000 == 0 {
return Err(std::io::Error::new(
std::io::ErrorKind::PermissionDenied,
format!("{} writable without sticky", path.display()),
));
}
ancestor = path.parent();
}
Ok(())
} Type guard
fn is_protected_dir(md: &std::fs::Metadata) -> bool {
let mode = md.mode();
mode & 0o022 == 0 || mode & 0o1000 != 0
} Prevention
- Mount only under root-owned directories like /Volumes or /mnt
- Run chmod +t on shared scratch parents used for mounts
- Audit ancestor permissions (ls -ld) in deployment scripts before mounting
- Never create mount parents with 0777
When it happens
Trigger: Calling mount/unmount (directly or via prepare_mountpoint, validate_mounted_mountpoint, validate_unmounted_mountpoint) when any parent directory of the mountpoint — e.g. /tmp/mnt with mode 0777 — is writable by non-owner and lacks the sticky bit.
Common situations: Mounting under a world-writable scratch directory such as /tmp/mymount where the user created a non-sticky subdirectory; CI containers where /var/mnt was created with 0777; reusing a shared build-artifact directory as a mount parent.
Understand the failure class
Background: "You do not have permission" / 403 Forbidden errors: authenticated but not allowed — causes and fixes across open-source libraries — this error's family across 31 libraries.
Related errors
- mountpoint contains traversal: {}
- private directory is not owned by the current user: {}
- private directory is not owner-only: {}
- trusted Windows parent has a null DACL: {description}
- legacy audit tree contains a redirect or boundary: {}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/96bd5de6e8d240ce.
Report an issue: GitHub.