Hmbown/CodeWhale · error

fleet task '{task_id}' {field} path '{}' cannot contain pare

Error message

fleet task '{task_id}' {field} path '{}' cannot contain parent traversal

What it means

After backslash-to-slash normalization and component checks, the path still contains a literal `..` segment (e.g. "../shared", "src/../../etc", or "..\\escape" which becomes "../escape"). This second pass exists because on Unix a path like "..\\x" is a legal single filename that the std::path component scan would not flag — the explicit split on '/' catches the obfuscated traversal. Paths must stay inside the task workspace.

Source

Thrown at crates/tui/src/fleet/worker_runtime.rs:363

            matches!(
                component,
                std::path::Component::ParentDir
                    | std::path::Component::RootDir
                    | std::path::Component::Prefix(_)
            )
        })
    {
        bail!(
            "fleet task '{task_id}' {field} path '{}' must be one repo-relative line and cannot escape the workspace",
            path.display()
        );
    }
    let mut segments = Vec::new();
    for segment in raw.split('/') {
        match segment {
            "" | "." => {}
            ".." => {
                bail!(
                    "fleet task '{task_id}' {field} path '{}' cannot contain parent traversal",
                    path.display()
                );
            }
            value => segments.push(value),
        }
    }
    Ok(if segments.is_empty() {
        ".".to_string()
    } else {
        segments.join("/")
    })
}

fn fleet_coordination_contracts(task_spec: &FleetTaskSpec) -> Result<Vec<String>> {
    let Some(value) = task_spec.metadata.get("coordination_contracts") else {
        return Ok(Vec::new());
    };

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Remove all `..` segments and state the target directly relative to the workspace root.
  2. If the target genuinely lives outside the repo, restructure so the task works on a copy inside the workspace, or use coordination contracts instead of a writable escape.
  3. Sanitize generated specs by canonicalizing and re-anchoring paths before emitting them.

Example fix

# before
[workspace]
writable_paths = ["src/../shared-lib"]

# after
[workspace]
writable_paths = ["shared-lib"]
Defensive patterns

Strategy: validation

Validate before calling

fn has_parent_traversal(path: &str) -> bool {
    path.replace('\\', "/").split('/').any(|seg| seg == "..")
}

assert!(!has_parent_traversal(&candidate));

Prevention

When it happens

Trigger: `writable_paths = [".."]`, `["src/../lib"]`, or backslash-encoded traversal like `["..\\shared\\out"]` in a TOML/JSON spec.

Common situations: Trying to grant write access to a sibling directory outside the workspace; leftover relative shorthands like "./../build"; adversarial specs probing sandbox boundaries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/d5c19684fa07e5ce. Report an issue: GitHub.