astrid-runtime/astrid · error
WinFsp service mountpoint is malformed
Error message
WinFsp service mountpoint is malformed
What it means
The mountpoint where the WinFsp filesystem will be attached must be a safe, absolute path. This error fires when the mountpoint is relative or contains a ParentDir ("..") component — i.e., the path could resolve somewhere unintended. Because a filesystem mount is a privileged operation, path-traversal-shaped mountpoints are rejected outright.
Source
Thrown at crates/astrid-storage-provider-winfsp/src/win.rs:296
let manifest_path = lease.resource_path.join("lease.json");
platform_fs::validate_private_file(&manifest_path)
.context("validate private WinFsp lease manifest")?;
let manifest = std::fs::read(&manifest_path).context("read WinFsp lease manifest")?;
if manifest.len() > 64 * 1024 {
bail!("WinFsp lease manifest exceeds the bounded size");
}
let admitted: StorageMountLeaseV1 =
serde_json::from_slice(&manifest).context("decode WinFsp lease manifest")?;
if admitted != *lease {
bail!("WinFsp launch lease does not match the kernel manifest");
}
if !launch.mountpoint.is_absolute()
|| launch
.mountpoint
.components()
.any(|component| matches!(component, std::path::Component::ParentDir))
{
bail!("WinFsp service mountpoint is malformed");
}
if is_public_mountpoint(&launch.mountpoint)
|| launch.mountpoint.parent().is_none()
|| launch.mountpoint == lease.resource_path
|| launch.mountpoint.starts_with(&lease.resource_path)
|| lease.resource_path.starts_with(&launch.mountpoint)
{
bail!("WinFsp service mountpoint is public or overlaps the lease resource");
}
platform_fs::validate_private_directory(&launch.mountpoint)
.context("validate private WinFsp mountpoint")?;
platform_fs::verify_no_redirects(&launch.mountpoint)
.context("reject redirected WinFsp mountpoint")?;
if std::fs::read_dir(&launch.mountpoint)?.next().is_some() {
bail!("WinFsp service mountpoint is not empty");
}
if !launch.control_path.is_absolute()
|| launchView on GitHub (pinned to affd8760f4)
Solutions
- Canonicalize the mountpoint in the launcher (fs::canonicalize / dunce::canonicalize) before embedding it in the launch descriptor.
- Reject or sanitize user input: ensure the mountpoint is absolute and free of ".." components at configuration time.
- Construct the mountpoint with PathBuf::join from a known root instead of string concatenation.
- If traversal is legitimate, resolve it in the trusted launcher (base.join(user_rel) then canonicalize) and pass the resolved absolute path.
Example fix
// before
mountpoint: PathBuf::from(format!("{}\\..\\mounts\\{}", base, id)),
// after
let mp = base.join("mounts").join(&id).canonicalize()?; // absolute, no ParentDir
mountpoint: mp, Defensive patterns
Strategy: validation
Validate before calling
let mp = dunce::canonicalize(&mountpoint)?;
if !mp.is_absolute() || mp.components().any(|c| matches!(c, std::path::Component::ParentDir)) {
return Err(anyhow!("mountpoint must be absolute with no '..' components"));
} Type guard
fn safe_mountpoint(p: &std::path::Path) -> bool {
p.is_absolute()
&& !p.components().any(|c| matches!(c, std::path::Component::ParentDir | std::path::Component::CurDir))
} Prevention
- Canonicalize mountpoints before embedding them in launch descriptors
- Validate user-supplied mount paths at configuration time, not at service start
- Build paths with PathBuf::join from a trusted root instead of string formatting
- Add a fuzz/property test asserting the launcher never emits ParentDir components
When it happens
Trigger: service_main -> validate_service_launch when !launch.mountpoint.is_absolute() or mountpoint.components() contains std::path::Component::ParentDir (e.g. "..\\mount", "C:\dir\..\mount", "mnt\\..\\x").
Common situations: Config files specifying relative mount directories resolved against an unexpected CWD; user-supplied mountpoints concatenated with ".." to escape a base dir; templates that build the mountpoint by string formatting instead of PathBuf::join/canonicalize; Windows drive-relative paths like "C:mount" which are not fully absolute.
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.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- WinFsp service mountpoint is public or overlaps the lease re
- WinFsp service mountpoint is not empty
- refusing to seed canonical from a non-content-address contra
- durable capsule {id} has unsafe WIT metadata path {relative}
- unsafe archive path '{path}'
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/f0c39136fd5eb55c.
Report an issue: GitHub.