Hmbown/CodeWhale · error
Codewhale-owned OAuth path escaped the credentials directory
Error message
Codewhale-owned OAuth path escaped the credentials directory
What it means
get_owned_credentials_at validates that the requested credential file's parent directory is exactly the Codewhale xAI OAuth credentials directory (xai_oauth_credentials_dir). Any other parent — including subdirectories or sibling paths — is rejected as a path-traversal guard for Codewhale-owned storage.
Solutions
- Use the library's own storage APIs (store.path_for / xai_oauth_credentials_dir) instead of constructing paths manually.
- Remove any ".." components or custom directories from the requested path.
- Check that the credentials directory isn't a symlink pointing outside the expected location.
Example fix
// before
let path = PathBuf::from("~/.codewhale/other/xai.json");
// after
let dir = codewhale_config::xai_oauth_credentials_dir()?;
let path = dir.join(provider.legacy_file_name()); Defensive patterns
Strategy: validation
Validate before calling
if (path.dirname(requested) !== codewhale.xaiOauthCredentialsDir()) throw new Error('use store.path_for'); Type guard
const inOwnedDir = (p, dir) => path.dirname(path.resolve(p)) === path.resolve(dir);
Try / catch
try { loadOwnedAt(p); } catch (e) { if (String(e).includes('escaped the credentials directory')) loadOwnedViaStore(); } Prevention
- Always derive credential paths from store.path_for, never from user input
- Avoid symlinking the credentials directory elsewhere
- Reject any path containing ".." before passing it to owned-storage APIs
When it happens
Trigger: Calling get_owned_credentials_at(provider, path) where path.parent() != xai_oauth_credentials_dir(), e.g. a path built from user input, "../", or a custom location.
Common situations: Scripting the credentials path with an env override or relative path; migrating an owned file manually to another directory; symlinked credentials directory resolving elsewhere.
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
- Codewhale-owned OAuth path has an invalid basename
- Codewhale-owned xAI OAuth DACL is not current-user-only
- Codewhale-owned xAI OAuth DACL must grant only one user
- Codewhale-owned xAI OAuth storage must have an owner-only…
- returned a verification URI with embedded credentials
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/6b1eba7a7b7d3551.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/oauth.rs:2200
bail!(
"Codewhale-owned {} OAuth credentials are not configured",
oauth_provider_params(provider).display_name
);
};
let name = path
.file_name()
.and_then(|name| name.to_str())
.context("Codewhale-owned OAuth path must have a UTF-8 basename")?;
codewhale_config::with_xai_oauth_lifecycle_lock(|store| {
get_owned_credentials_locked(provider, store, name, |issuer, client_id, refresh| {
refresh_for_provider(provider, client, issuer, client_id, refresh)
})
})
}
fn get_owned_credentials_at(provider: OAuthProvider, path: &Path) -> Result<OwnedOAuthCredentials> {
let directory = codewhale_config::xai_oauth_credentials_dir()?;
anyhow::ensure!(
path.parent() == Some(directory.as_path()),
"Codewhale-owned OAuth path escaped the credentials directory"
);
let name = path
.file_name()
.and_then(|name| name.to_str())
.context("Codewhale-owned OAuth path must have a UTF-8 basename")?;
anyhow::ensure!(
name == provider.legacy_file_name() || provider.is_valid_generation(name),
"Codewhale-owned OAuth path has an invalid basename"
);
codewhale_config::with_xai_oauth_lifecycle_lock(|store| {
get_owned_credentials_locked(provider, store, name, |issuer, client_id, refresh| {
refresh_for_provider(
provider,
&ReqwestOAuthFormClient,
issuer,
client_id,View on GitHub (pinned to 73e0f67d83)