Hmbown/CodeWhale · error
skill path {} escapes skills directory {}
Error message
skill path {} escapes skills directory {} What it means
Guard in ensure_target_within_skills_dir fired because the computed install target for the skill resolves to a path outside the configured skills directory. The skill name (or archive layout) produced a target containing traversal or an absolute component, so installing it would write outside CodeWhale-owned storage; this is a path-traversal rejection, not a filesystem failure.
Source
Thrown at crates/tui/src/skills/install.rs:1564
bail!("skill name must be a single path-safe segment (got '{name}')");
}
if name == "." || name == ".." || name.contains('/') || name.contains('\\') {
bail!("skill name must be a single path-safe segment (got '{name}')");
}
let mut components = Path::new(name).components();
if !matches!(components.next(), Some(Component::Normal(_))) || components.next().is_some() {
bail!("skill name must be a single path-safe segment (got '{name}')");
}
Ok(name)
}
fn ensure_target_within_skills_dir(target: &Path, skills_dir: &Path) -> Result<()> {
let skills_dir = fs::canonicalize(skills_dir)
.with_context(|| format!("failed to resolve {}", skills_dir.display()))?;
let target = fs::canonicalize(target)
.with_context(|| format!("failed to resolve {}", target.display()))?;
if !target.starts_with(&skills_dir) {
bail!(
"skill path {} escapes skills directory {}",
target.display(),
skills_dir.display()
);
}
Ok(())
}
/// Strip a leading directory prefix (e.g. `repo-main/`) from a tarball path.
fn strip_prefix<'a>(path: &'a str, prefix: &str) -> std::borrow::Cow<'a, str> {
if prefix.is_empty() {
return std::borrow::Cow::Borrowed(path);
}
let with_slash = format!("{prefix}/");
if let Some(rest) = path.strip_prefix(&with_slash) {
std::borrow::Cow::Owned(rest.to_string())
} else if path == prefix {
std::borrow::Cow::Borrowed("")View on GitHub (pinned to 0c42157ee5)
Solutions
- Reject the skill source; its declared name or layout produces an unsafe target path
- Ask the skill author to rename the skill to a single path-safe segment
- If installing from an archive, verify the top-level directory name contains no '..' or separators
- Install to the correct skills directory so the resolved target stays inside it
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at crates/tui/src/skills/install.rs:1564 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/6fed1a21c906c712.
Report an issue: GitHub.