{"record":{"id":"8bad98f61e5bde18","repo":"Hmbown/CodeWhale","slug":"codewhale-owned-xai-oauth-path-must-not-be-a-repar","errorCode":null,"errorMessage":"Codewhale-owned xAI OAuth path must not be a reparse point","messagePattern":"Codewhale-owned xAI OAuth path must not be a reparse point","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/config/src/xai_credentials.rs","lineNumber":1209,"sourceCode":"    expected: &Path,\n    expect_directory: bool,\n) -> Result<fs::Metadata> {\n    use std::ffi::OsString;\n    use std::os::windows::ffi::OsStringExt as _;\n    use std::os::windows::fs::MetadataExt as _;\n    use std::os::windows::io::AsRawHandle as _;\n    use windows_sys::Win32::Storage::FileSystem::{\n        FILE_ATTRIBUTE_REPARSE_POINT, FILE_NAME_NORMALIZED, GetFinalPathNameByHandleW,\n        VOLUME_NAME_DOS,\n    };\n\n    let metadata = file.metadata().with_context(|| {\n        format!(\n            \"inspecting Codewhale-owned path {}\",\n            crate::quote_os_path(expected)\n        )\n    })?;\n    anyhow::ensure!(\n        metadata.file_attributes() & FILE_ATTRIBUTE_REPARSE_POINT == 0,\n        \"Codewhale-owned xAI OAuth path must not be a reparse point\"\n    );\n    anyhow::ensure!(\n        if expect_directory {\n            metadata.is_dir()\n        } else {\n            metadata.is_file()\n        },\n        \"Codewhale-owned xAI OAuth path has the wrong filesystem type\"\n    );\n    let flags = FILE_NAME_NORMALIZED | VOLUME_NAME_DOS;\n    let handle = file.as_raw_handle();\n    // SAFETY: null output asks only for the required UTF-16 length.\n    let needed = unsafe { GetFinalPathNameByHandleW(handle, std::ptr::null_mut(), 0, flags) };\n    if needed == 0 {\n        return Err(std::io::Error::last_os_error())\n            .context(\"resolving Codewhale-owned xAI OAuth handle path\");","sourceCodeStart":1191,"sourceCodeEnd":1227,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/config/src/xai_credentials.rs#L1191-L1227","documentation":"Every windows handle is opened with FILE_FLAG_OPEN_REPARSE_POINT and then rejected when its attributes include FILE_ATTRIBUTE_REPARSE_POINT. This makes symlinks and junctions fail closed for the credentials leaf, every ancestor component, and every credential file, preserving the lexical Codewhale-owned boundary so an external directory can never impersonate the store.","triggerScenarios":"$CODEWHALE_HOME or any ancestor is a symlink/junction (dotfile managers, relocated profiles); the credentials directory itself is a symlink to another location; cloud-sync placeholder reparse tags also carry the attribute.","commonSituations":"Users symlinking ~/.codewhale into a synced or shared folder; Windows profile junctions; dev boxes redirecting home with directory links.","solutions":["Replace the link with a real directory: remove the junction/symlink (rmdir or del on the link only), create a real directory, then re-run codewhale auth xai-device","Point CODEWHALE_HOME at a real local NTFS directory instead of linking to one","Move the actual directory to the expected location rather than linking to it"],"exampleFix":"# before (PowerShell)\nNew-Item -ItemType SymbolicLink -Path \"$env:USERPROFILE\\.codewhale\" -Target \"D:\\sync\\codewhale\"\n\n# after\nRemove-Item \"$env:USERPROFILE\\.codewhale\"      # removes the link only\nNew-Item -ItemType Directory -Path \"$env:USERPROFILE\\.codewhale\"\ncodewhale auth xai-device","handlingStrategy":"validation","validationCode":"#[cfg(windows)]\nfn no_reparse_ancestry(p: &std::path::Path) -> bool {\n    p.ancestors().all(|a| {\n        std::fs::symlink_metadata(a)\n            .map(|m| !m.file_type().is_symlink())\n            .unwrap_or(true)\n    })\n}","typeGuard":"#[cfg(windows)]\nfn path_is_link_free(p: &std::path::Path) -> bool {\n    std::fs::symlink_metadata(p)\n        .map(|m| !m.file_type().is_symlink())\n        .unwrap_or(true)\n}","tryCatchPattern":null,"preventionTips":["Use a real directory for CODEWHALE_HOME, never a symlink or junction","Keep dotfile managers away from .codewhale","After moving home directories, replace links with the real folder and re-login"],"tags":["windows","security","symlink","filesystem","xai-oauth"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}