Hmbown/CodeWhale · error

workspace path cannot contain '..' components

Error message

workspace path cannot contain '..' components

What it means

`checked_workspace_path` rejects workspace paths containing `..` components to guarantee the derived `.codewhale/mcp.json` location stays unambiguous and cannot traverse outside the intended workspace. The library treats parent-dir components in a workspace root as invalid input rather than normalizing them away.

Solutions

  1. Canonicalize the workspace before passing it in: `workspace.canonicalize()?` removes `..` components
  2. Convert the path to an absolute path via `std::env::current_dir()?.join(rel)` then `normalize_path_components`
  3. Fix the stored configuration to use an absolute, `..`-free workspace path

Example fix

// before
let workspace = PathBuf::from("../other-project");
// after
let workspace = PathBuf::from("../other-project").canonicalize()?; // absolute, no '..' components
Defensive patterns

Strategy: validation

Validate before calling

use std::path::Component;
if workspace.components().any(|c| matches!(c, Component::ParentDir)) {
    let workspace = workspace.canonicalize()?;
}

Type guard

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

Try / catch

let workspace = workspace.canonicalize().map_err(|e| anyhow::anyhow!("cannot normalize workspace {workspace:?}: {e}"))?;

Prevention

When it happens

Trigger: Passing a workspace like `Path::new("../myproject")` or `./a/../b` into any MCP config function that routes through `checked_workspace_path` (crates/tui/src/mcp.rs:5619).

Common situations: Users typing relative `../` paths on the command line; scripts building workspace paths by concatenation; config values copied with trailing relative segments.

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 Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/00fabcb95e11ebf4. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/mcp.rs:5619

fn workspace_allows_project_mcp_config(workspace: &Path) -> bool {
    crate::config::is_workspace_trusted(workspace)
}

fn checked_workspace_mcp_config_path(workspace: &Path) -> Result<PathBuf> {
    Ok(checked_workspace_path(workspace)?
        .join(".codewhale")
        .join("mcp.json"))
}

fn checked_workspace_path(workspace: &Path) -> Result<PathBuf> {
    if workspace.as_os_str().is_empty() {
        anyhow::bail!("workspace path cannot be empty");
    }
    if workspace
        .components()
        .any(|component| matches!(component, Component::ParentDir))
    {
        anyhow::bail!("workspace path cannot contain '..' components");
    }
    let absolute = if workspace.is_absolute() {
        workspace.to_path_buf()
    } else {
        std::env::current_dir()
            .context("failed to resolve current directory for workspace")?
            .join(workspace)
    };
    match absolute.canonicalize() {
        Ok(path) => Ok(path),
        Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
            Ok(normalize_path_components(&absolute))
        }
        Err(err) => {
            Err(err).with_context(|| format!("failed to resolve workspace {}", workspace.display()))
        }
    }
}

View on GitHub (pinned to 73e0f67d83)