BigPizzaV3/CodexPlusPlus · error
Parent traversal is unsupported
Error message
Parent traversal is unsupported
What it means
As the final plain_path check, the component list of the path is scanned for Component::ParentDir (`..`). Parent traversal could escape the intended root after pinning, defeating the isolation contract, so any path containing `..` is rejected.
Solutions
- Remove `..` from the configured path and express the real absolute location directly
- Normalize the path before calling: std::path::absolute plus lexical cleanup, or fs::canonicalize (after ensuring no links)
- Sanitize untrusted input: reject any path whose components include ParentDir before passing to the API
- Keep paths built with PathBuf::join from trusted constants rather than string concatenation of user input
Example fix
// before
plain_path(&Path::new("C:\\codex\\..\\codex-browser\\state"))?;
// after
plain_path(&Path::new("C:\\codex-browser\\state"))?; Defensive patterns
Strategy: validation
Validate before calling
fn contains_parent_dir(p: &Path) -> bool {
p.components().any(|c| matches!(c, std::path::Component::ParentDir))
} Type guard
fn is_traversal_free(p: &Path) -> bool {
!p.components().any(|c| matches!(c, std::path::Component::ParentDir))
} Try / catch
match plain_path(p) {
Err(e) if e.to_string().contains("Parent traversal") => {
eprintln!("path contains '..'; specify the real absolute location instead");
}
other => other?,
} Prevention
- Reject '..' segments in user-supplied paths at config validation time
- Normalize paths with canonicalize/absolute before storing them
- Build paths with PathBuf::join on trusted roots, not string concatenation
When it happens
Trigger: pin_parents, selected_key, discover, prepare, restore_all, or reconcile_contract given a path built with `..` segments — e.g. root.join("..")\sibling or user-supplied relative-ish input that includes .. even when overall absolute.
Common situations: User config like `state_root = "C:\\codex\\..\\codex-browser"`; code normalizing via join("..") instead of canonicalize; untrusted input containing .. reaching the browser path configuration.
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
- 无效的市场主题下载文件名
- Linked paths are unsupported
- archived lookup task failed
- Backup source database is not an allowed local storage path
- built-in Dream Skin theme cannot be deleted
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19).
Data as JSON: /api/errors/8c24b5764e00db85.
Report an issue: GitHub.
Appendix: source
Thrown at crates/codex-plus-core/src/native_browser.rs:127
fn plain_path(path: &Path) -> Result<()> {
ensure!(path.is_absolute(), "Expected an absolute local path");
for ancestor in path.ancestors() {
if let Ok(meta) = fs::symlink_metadata(ancestor) {
ensure!(
!meta.file_type().is_symlink(),
"Linked paths are unsupported"
);
#[cfg(windows)]
{
use std::os::windows::fs::MetadataExt;
ensure!(
meta.file_attributes() & 0x400 == 0,
"Reparse paths are unsupported"
);
}
}
}
ensure!(
!path
.components()
.any(|c| matches!(c, std::path::Component::ParentDir)),
"Parent traversal is unsupported"
);
Ok(())
}
// Deny directory deletion/renaming while a Windows transaction uses its descendants.
// Open root-first with OPEN_REPARSE_POINT so no checked parent can become a junction.
fn pin_parents(path: &Path) -> Result<Vec<File>> {
plain_path(path)?;
let mut guards = Vec::new();
#[cfg(windows)]
{
use std::os::windows::fs::{MetadataExt, OpenOptionsExt};
let mut parents: Vec<_> = path.ancestors().skip(1).collect();
parents.reverse();View on GitHub (pinned to b1ed92e5e4)