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
- Remove all `..` segments and state the target directly relative to the workspace root.
- 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.
- 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
- Normalize with the same rule the runtime uses: backslashes are separators, '..' segments are fatal.
- Generate paths by joining cleaned segments, never by string-concatenating user input.
- Remember Unix treats '..\\x' as one filename — validate on the normalized form, not the raw one.
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
- fleet task '{task_id}' {field} path '{}' must be one repo-re
- agent profile {} may not request allow_shell=true
- agent profile {} may not request trust=true
- external credential path escapes its absolute root: {}
- external credential path must resolve to an absolute path: {
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/d5c19684fa07e5ce.
Report an issue: GitHub.