astrid-runtime/astrid · error
WinFsp service control path is malformed
Error message
WinFsp service control path is malformed
What it means
validate_service_launch rejects a WinFsp service launch whose control_path fails structural or canonical-form checks: it must not contain '..' components, and it must exactly equal the lease resource path joined with "process-control.sock". The library enforces this so the private control socket lands in a predictable, non-escapable location tied to the mount lease.
Solutions
- Set control_path to exactly lease.resource_path.join("process-control.sock") and let the library derive it rather than hardcoding it.
- Remove any '..' components from control_path by canonicalizing the resource path before building the launch struct.
- If you need a different socket location, change the lease resource_path, not the control_path.
Example fix
// before
launch.control_path = PathBuf::from("/var/run/mounts/../m-123/process-control.sock");
// after
launch.control_path = lease.resource_path.join("process-control.sock"); Defensive patterns
Strategy: validation
Validate before calling
let expected = lease.resource_path.join("process-control.sock");
if launch.control_path != expected
|| launch.control_path.components().any(|c| matches!(c, std::path::Component::ParentDir)) {
return Err(anyhow!("control_path must be {:?}", expected));
} Type guard
fn control_path_is_canonical(launch: &StorageProviderServiceLaunchV1, lease: &Lease) -> bool {
launch.control_path == lease.resource_path.join("process-control.sock")
&& !launch.control_path.components().any(|c| matches!(c, std::path::Component::ParentDir))
} Try / catch
match validate_service_launch(&launch) {
Err(e) if e.to_string().contains("control path is malformed") => {
// rebuild control_path from lease and retry once
},
other => other?,
} Prevention
- Always derive control_path from lease.resource_path, never hardcode it.
- Canonicalize resource_path with its components before building the launch.
- Add a unit test asserting control_path == resource_path.join("process-control.sock").
When it happens
Trigger: Calling the WinFsp service entry (service_main -> validate_service_launch) with a StorageProviderServiceLaunchV1 whose control_path contains a ParentDir ('..') component, or whose control_path differs from lease.resource_path.join("process-control.sock").
Common situations: Hand-constructed launch configs for testing; templating bugs that resolve or relativize paths with '..'; moving the control socket to a custom directory for shared mounts; tools that normalize paths (e.g. a/../b) before passing them in.
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
- capsule materialization target is redirected or not a…
- capsule ' ' is outside the explicit workspace portal and…
- is not a canonical cache component
- layout path is redirected or not a directory
- named-pipe endpoint path must not contain a parent component
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/fa2effa128f776f8.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-storage-provider-winfsp/src/win.rs:320
|| 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()
|| launch
.control_path
.components()
.any(|component| matches!(component, std::path::Component::ParentDir))
|| launch.control_path != lease.resource_path.join("process-control.sock")
{
bail!("WinFsp service control path is malformed");
}
let control_parent = launch
.control_path
.parent()
.context("WinFsp service control path has no parent")?;
platform_fs::validate_private_directory(control_parent)
.context("validate private WinFsp control parent")?;
platform_fs::verify_no_redirects(&launch.control_path)
.context("reject redirected WinFsp control path")?;
if local_transport::endpoint_is_present(&launch.control_path)
.context("inspect WinFsp service control endpoint")?
{
bail!("WinFsp service control endpoint is already present");
}
Ok(())
}
async fn probe_callback(launch: &StorageProviderServiceLaunchV1) -> Result<()> {View on GitHub (pinned to affd8760f4)