{"record":{"id":"5379fef8095e4150","repo":"BigPizzaV3/CodexPlusPlus","slug":"reparse-paths-are-unsupported","errorCode":null,"errorMessage":"Reparse paths are unsupported","messagePattern":"Reparse paths are unsupported","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codex-plus-core/src/native_browser.rs","lineNumber":120,"sourceCode":"}\n\nfn key_valid(key: &str) -> bool {\n    key.len() == 16 && key.bytes().all(|b| b.is_ascii_hexdigit())\n}\n\n// Reject junctions as well as symlinks, including in parent directories.\nfn plain_path(path: &Path) -> Result<()> {\n    ensure!(path.is_absolute(), \"Expected an absolute local path\");\n    for ancestor in path.ancestors() {\n        if let Ok(meta) = fs::symlink_metadata(ancestor) {\n            ensure!(\n                !meta.file_type().is_symlink(),\n                \"Linked paths are unsupported\"\n            );\n            #[cfg(windows)]\n            {\n                use std::os::windows::fs::MetadataExt;\n                ensure!(\n                    meta.file_attributes() & 0x400 == 0,\n                    \"Reparse paths are unsupported\"\n                );\n            }\n        }\n    }\n    ensure!(\n        !path\n            .components()\n            .any(|c| matches!(c, std::path::Component::ParentDir)),\n        \"Parent traversal is unsupported\"\n    );\n    Ok(())\n}\n\n// Deny directory deletion/renaming while a Windows transaction uses its descendants.\n// Open root-first with OPEN_REPARSE_POINT so no checked parent can become a junction.\nfn pin_parents(path: &Path) -> Result<Vec<File>> {","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/b1ed92e5e4a2d74095d4b8db5af43cef7acba9c6/crates/codex-plus-core/src/native_browser.rs#L102-L138","documentation":"On Windows, plain_path additionally inspects file_attributes for the reparse-point bit (0x400). Beyond symlinks/junctions, other reparse-tag entries (mount points, OneDrive placeholder files, AppExecLink etc.) can change path resolution semantics, so any ancestor with the reparse bit is rejected.","triggerScenarios":"Any plain_path caller traverses an ancestor whose symlink_metadata has FILE_ATTRIBUTE_REPARSE_POINT set — e.g. a runtime root inside an OneDrive-synced folder, Dev Drive mount points, or store-app AppExecLink directories.","commonSituations":"Configuring the browser root under OneDrive/Documents/Cloud-synced folders; using directories inside mounted VHDs or DFS paths; paths under WindowsApps or other reparse-backed locations.","solutions":["Move the browser runtime/state roots to a plain local NTFS directory with no reparse points in the ancestry","Disable OneDrive sync/placeholders for the folder or exclude it, then copy the data to a local path","Check the attribute before configuring: (fs::symlink_metadata(p)?.file_attributes() & 0x400) == 0","Update the configured path to a non-reparse location (e.g. C:\\\\codex-browser\\\\...)"],"exampleFix":"// before: root under OneDrive placeholder folder\nruntime_root = \"C:\\\\Users\\\\me\\\\OneDrive\\\\browser-runtime\"\n// after: plain local folder\nruntime_root = \"C:\\\\codex-browser\\\\runtime\"","handlingStrategy":"validation","validationCode":"#[cfg(windows)]\nfn has_reparse_ancestor(p: &Path) -> bool {\n    use std::os::windows::fs::MetadataExt;\n    p.ancestors().any(|a| fs::symlink_metadata(a).map(|m| m.file_attributes() & 0x400 != 0).unwrap_or(false))\n}","typeGuard":null,"tryCatchPattern":"match plain_path(p) {\n    Err(e) if e.to_string().contains(\"Reparse paths\") => {\n        eprintln!(\"{} is inside a reparse-point location (OneDrive/mount); relocate to plain NTFS\", p.display());\n    }\n    other => other?,\n}","preventionTips":["Keep browser roots out of OneDrive/cloud-sync and mounted-volume locations","Prefer plain local NTFS directories (e.g. under LOCALAPPDATA or a dedicated C:\\\\ folder)","Pre-check the reparse bit on all ancestors during setup"],"tags":["rust","windows","reparse-point"],"backgroundTag":"path-traversal-blocked","analyzedSha":"b1ed92e5e4a2d74095d4b8db5af43cef7acba9c6","analyzedAt":"2026-09-19T23:35:21.129Z","contentChangedAt":"2026-09-19T23:35:21.129Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}