Hmbown/CodeWhale · error · anyhow::Error
config path cannot contain '..' components
Error message
config path cannot contain '..' components
What it means
Thrown by normalize_config_file_path when the config path contains at least one '..' (ParentDir) component. This is a deliberate path-traversal guard: the resolved config location must be expressible without parent references, so the normalizer rejects the input before resolving it against the current directory.
Source
Thrown at crates/config/src/lib.rs:6619
redact_toml_value_for_display_inner(&path, sensitive, child_value),
);
}
toml::Value::Table(redacted)
}
_ if sensitive => toml::Value::String("********".to_string()),
_ => value.clone(),
}
}
fn normalize_config_file_path(path: PathBuf) -> Result<PathBuf> {
if path.as_os_str().is_empty() {
bail!("config path cannot be empty");
}
if path
.components()
.any(|component| matches!(component, Component::ParentDir))
{
bail!("config path cannot contain '..' components");
}
if path.file_name().is_none() {
bail!("config path must include a file name");
}
let absolute = if path.is_absolute() {
path
} else {
std::env::current_dir()
.context("failed to resolve current directory for config path")?
.join(path)
};
let file_name = absolute
.file_name()
.map(OsString::from)
.context("config path must include a file name")?;
let parent = absolute
.parent()
.context("config path must include a parent directory")?;View on GitHub (pinned to 0c42157ee5)
Solutions
- Pass an absolute path with no '..' components, e.g. /home/user/shared/codewhale.toml
- Or pass a path relative to the current directory that stays inside it, e.g. config/codewhale.toml
- Canonicalize the path in your own shell/script first (realpath) and pass the result, which contains no parent components
Example fix
# before codewhale --config ../shared/codewhale.toml # after codewhale --config "$(realpath ../shared/codewhale.toml)"
Defensive patterns
Strategy: validation
Validate before calling
use std::path::{Component, Path};
fn traversal_free(p: &Path) -> bool {
!p.components().any(|c| matches!(c, Component::ParentDir))
}
assert!(traversal_free(Path::new(&flag)), "config path must not contain '..'"); Type guard
fn is_traversal_free(p: &std::path::Path) -> bool {
!p.components().any(|c| matches!(c, std::path::Component::ParentDir))
} Prevention
- Canonicalize config paths (realpath/dunce::canonicalize) before handing them to codewhale
- Store canonical absolute config paths in your tooling config instead of relative ones with '..'
- Treat any '..' in user-supplied paths as invalid input at parse time
When it happens
Trigger: `--config ../shared/codewhale.toml`, `--config ./releases/../../config.toml`, or any relative path that walks upward. The check runs on the raw components, so the '..' is rejected even when it would lexically cancel out.
Common situations: Keeping a shared config in a parent directory; monorepo setups reaching for ../../team-config.toml; attempting to work around the symlink rejection (error 148) by pointing through '..'; scripts building paths via concat(cwd, '/../x').
Related errors
- persistent path allow rules must stay within the workspace
- project workspace path cannot contain '..' components
- config path must not be a symlink: {}
- {kind} must be a single path component
- Project MCP server cwd must stay within workspace: {}
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/0a7a1137bc1fa432.
Report an issue: GitHub.