{"record":{"id":"f4c5a8ea86dd2a1f","repo":"Hmbown/CodeWhale","slug":"external-credential-path-contains-reparse-point","errorCode":null,"errorMessage":"external credential path contains reparse point {}","messagePattern":"external credential path contains reparse point (.+?)","errorType":"validation","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/external_credentials.rs","lineNumber":622,"sourceCode":"}\n\n#[cfg(windows)]\nfn reject_windows_reparse_components(path: &Path) -> io::Result<()> {\n    use std::os::windows::fs::MetadataExt;\n    use windows_sys::Win32::Storage::FileSystem::FILE_ATTRIBUTE_REPARSE_POINT;\n\n    let mut current = std::path::PathBuf::new();\n    for component in path.components() {\n        current.push(component.as_os_str());\n        if matches!(\n            component,\n            std::path::Component::Prefix(_) | std::path::Component::RootDir\n        ) {\n            continue;\n        }\n        let metadata = std::fs::symlink_metadata(&current)?;\n        if metadata.file_attributes() & FILE_ATTRIBUTE_REPARSE_POINT != 0 {\n            return Err(io::Error::new(\n                io::ErrorKind::PermissionDenied,\n                format!(\n                    \"external credential path contains reparse point {}\",\n                    codewhale_config::quote_os_path(&current)\n                ),\n            ));\n        }\n    }\n    Ok(())\n}\n\n#[cfg(not(any(unix, windows)))]\nfn open_secure_regular_file(_path: &Path, _require_owner_only: bool) -> io::Result<File> {\n    Err(io::Error::new(\n        io::ErrorKind::Unsupported,\n        \"secure external credential reads are unsupported on this platform\",\n    ))\n}","sourceCodeStart":604,"sourceCodeEnd":640,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/external_credentials.rs#L604-L640","documentation":"This error means a component of the credential file path is (or is inside) a reparse point such as a symlink or junction. Codewhale walks each path component and rejects any with FILE_ATTRIBUTE_REPARSE_POINT to prevent symlink-based escapes from the intended file location.","triggerScenarios":"Calling open_secure_regular_file (via read_to_string / read_codewhale_owned_to_string) with a path that contains a symbolic link, junction, or mount-point directory, or whose parent directories are symlinks.","commonSituations":"Credential path configured through a symlinked dotfiles directory (e.g. dotfiles managed with symlinks under Dropbox/chezmoi); a junctioned profile directory; a redirected config path pointing at a link.","solutions":["Point the configuration at the real, non-symlink physical path of the credential file","Replace the symlink with a real copy (or hardlink-free duplicate) of the credential file","On Windows, ensure no junction/mount point exists in any parent directory of the path"],"exampleFix":"// before\ncredentials_path = C:\\Users\\me\\dotfiles\\cred.json  # symlink\n// after\ncredentials_path = C:\\Users\\me\\AppData\\Roaming\\Codewhale\\cred.json","handlingStrategy":"validation","validationCode":"fn path_has_no_reparse(path: &std::path::Path) -> bool {\n    let mut cur = path.to_path_buf();\n    while let Some(parent) = cur.parent() {\n        if let Ok(md) = std::fs::symlink_metadata(&cur) {\n            #[cfg(windows)]\n            if md.file_attributes() & 0x400 != 0 { return false; } // FILE_ATTRIBUTE_REPARSE_POINT\n        }\n        cur = parent.to_path_buf();\n    }\n    true\n}","typeGuard":null,"tryCatchPattern":"match read_to_string(path) {\n    Ok(s) => use_credential(&s),\n    Err(e) if e.kind() == std::io::ErrorKind::PermissionDenied => {\n        eprintln!(\"path contains a symlink/reparse point; use the physical path\");\n    }\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Configure absolute, physical paths for credentials — never through symlinked dotfiles","Test your configured path with symlink_metadata before relying on it","Avoid junctioned or redirected profile directories for credential storage"],"tags":["windows","symlink","path-traversal","security"],"backgroundTag":"path-traversal-blocked","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}