{"record":{"id":"99a21a3452b79781","repo":"Hmbown/CodeWhale","slug":"codewhale-owned-xai-oauth-dacl-is-not-current-user","errorCode":null,"errorMessage":"Codewhale-owned xAI OAuth DACL is not current-user-only","messagePattern":"Codewhale-owned xAI OAuth DACL is not current-user-only","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/config/src/xai_credentials.rs","lineNumber":1390,"sourceCode":"    );\n    let mut count = 0;\n    let mut entries: *mut EXPLICIT_ACCESS_W = std::ptr::null_mut();\n    // SAFETY: `dacl` belongs to the live descriptor; Windows allocates the\n    // returned entry array, released by the guard below.\n    let result = unsafe { GetExplicitEntriesFromAclW(dacl, &mut count, &mut entries) };\n    if result != ERROR_SUCCESS {\n        return Err(std::io::Error::from_raw_os_error(result as i32))\n            .context(\"reading Codewhale-owned xAI OAuth DACL entries\");\n    }\n    let _entries = WindowsLocalAllocation(entries.cast());\n    anyhow::ensure!(\n        count == 1 && !entries.is_null(),\n        \"Codewhale-owned xAI OAuth DACL must grant only one user\"\n    );\n    // SAFETY: `count == 1` proves the first returned entry is initialized.\n    let entry = unsafe { &*entries };\n    let trustee_sid: PSID = entry.Trustee.ptstrName.cast();\n    anyhow::ensure!(\n        entry.Trustee.TrusteeForm == TRUSTEE_IS_SID\n            && !trustee_sid.is_null()\n            && unsafe { EqualSid(trustee_sid, user.sid()) } != 0\n            && matches!(entry.grfAccessMode, SET_ACCESS | GRANT_ACCESS)\n            && entry.grfAccessPermissions == FILE_ALL_ACCESS,\n        \"Codewhale-owned xAI OAuth DACL is not current-user-only\"\n    );\n    Ok(())\n}\n\n#[cfg(windows)]\nstruct CurrentWindowsUser {\n    token: windows_sys::Win32::Foundation::HANDLE,\n    token_info: Vec<usize>,\n}\n\n#[cfg(windows)]\nimpl CurrentWindowsUser {","sourceCodeStart":1372,"sourceCodeEnd":1408,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/config/src/xai_credentials.rs#L1372-L1408","documentation":"The final windows DACL check requires the single ACE to identify the current user by SID (TRUSTEE_IS_SID), use SET_ACCESS or GRANT_ACCESS mode, and grant exactly FILE_ALL_ACCESS. Any other trustee, a reduced access mask, or a deny-style entry fails closed — including files whose grant belongs to a different account than the one running codewhale.","triggerScenarios":"Credential files copied from another user or machine (the SID belongs elsewhere); partial icacls edits leaving a restricted mask; tools writing deny ACEs.","commonSituations":"Migrating logins between accounts by copying files; manual permission surgery; shared machines.","solutions":["Delete the credential files in $CODEWHALE_HOME/credentials and run codewhale auth xai-device again on this account","Or repair the ACE: icacls <file> /inheritance:r then icacls <file> /grant:r \"%USERNAME%:F\"","Never copy OAuth files between accounts; re-authenticate instead"],"exampleFix":":: before (file copied from another account)\n:: after\nicacls \"%USERPROFILE%\\.codewhale\\credentials\\xai-auth.json\" /inheritance:r\nicacls \"%USERPROFILE%\\.codewhale\\credentials\\xai-auth.json\" /grant:r \"%USERNAME%:F\ncodewhale auth xai-device","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"match login() {\n    Ok(v) => v,\n    Err(e) if e.to_string().contains(\"DACL is not current-user-only\") => {\n        // files copied from another account: delete and re-authenticate\n        let _ = std::fs::remove_dir_all(&credentials_dir);\n        login()?\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Never copy OAuth credential files between users or machines; re-authenticate","Avoid manual icacls surgery on credential files","When migrating accounts, wipe the credentials directory first and log in again"],"tags":["windows","security","acl","permissions","xai-oauth"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}