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

  1. Set control_path to exactly lease.resource_path.join("process-control.sock") and let the library derive it rather than hardcoding it.
  2. Remove any '..' components from control_path by canonicalizing the resource path before building the launch struct.
  3. 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

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.

Related errors


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)