astrid-runtime/astrid · error

FSKit service control path is malformed

Error message

FSKit service control path is malformed

What it means

validate_control_path requires the service control path to be absolute and free of ParentDir (..) components. Paths with '..' can escape the intended private directory, so they are rejected as malformed before any filesystem access.

Solutions

  1. Provide an absolute, '..'-free control path equal to resource_path/process-control.sock
  2. Normalize the path with components()/clean before validating (must still be absolute afterwards)
  3. Reject or fix upstream input that injects '..' segments

Example fix

// before
control_path: "/var/fskit/leases/a/../ctl.sock".into()
// after
control_path: "/var/fskit/leases/a/process-control.sock".into()
Defensive patterns

Strategy: validation

Validate before calling

fn control_path_ok(p: &std::path::Path) -> bool {
    p.is_absolute()
        && !p.components().any(|c| matches!(c, std::path::Component::ParentDir))
}

Type guard

fn has_parent_dir(p: &std::path::Path) -> bool {
    p.components().any(|c| matches!(c, std::path::Component::ParentDir))
}

Prevention

When it happens

Trigger: validate_launch passes a control_path that is relative or contains '..' segments (e.g. "/var/fskit/../tmp/ctl.sock" or "ctl.sock").

Common situations: String-concatenated paths from templates or CLI args; user-supplied paths not normalized; configs that use ../ to work around directory layout.

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/82f81a2586a49541. Report an issue: GitHub.

Appendix: source

Thrown at crates/astrid-storage-provider-fskit/src/service.rs:188

        .context("read FSKit lease manifest")?;
    if manifest.len() > 64 * 1024 {
        bail!("FSKit lease manifest exceeds the bounded size");
    }
    let admitted: astrid_core::storage_filesystem::StorageMountLeaseV1 =
        serde_json::from_slice(&manifest).context("decode FSKit lease manifest")?;
    if admitted != *lease {
        bail!("FSKit launch lease does not match the kernel manifest");
    }
    Ok(())
}

fn validate_control_path(control_path: &Path, resource_path: &Path) -> Result<()> {
    if !control_path.is_absolute()
        || control_path
            .components()
            .any(|component| matches!(component, std::path::Component::ParentDir))
    {
        bail!("FSKit service control path is malformed");
    }
    let parent = control_path
        .parent()
        .context("FSKit service control path has no parent")?;
    platform_fs::validate_private_directory(parent)
        .context("validate private FSKit control parent")?;
    platform_fs::verify_no_redirects(control_path)
        .context("reject redirected FSKit control path")?;
    if control_path != resource_path.join("process-control.sock") {
        bail!("FSKit service control path is not the kernel endpoint");
    }
    if local_transport::endpoint_is_present(control_path)
        .context("inspect FSKit service control endpoint")?
    {
        bail!("FSKit service control endpoint is already present");
    }
    Ok(())
}

View on GitHub (pinned to affd8760f4)