Hmbown/CodeWhale · error

Codewhale-owned xAI OAuth DACL must grant only one user

Error message

Codewhale-owned xAI OAuth DACL must grant only one user

What it means

The verifier enumerates the DACL's explicit entries with GetExplicitEntriesFromAclW and requires exactly one ACE. Credentials written by older versions (before the protected owner-only DACL) can carry inherited or additional entries, and manual icacls grants also add entries, so the strict one-entry policy fails closed on them.

Source

Thrown at crates/config/src/xai_credentials.rs:1383

    anyhow::ensure!(
        !owner.is_null() && unsafe { EqualSid(owner, user.sid()) } != 0,
        "Codewhale-owned xAI OAuth storage owner is not the current user"
    );
    anyhow::ensure!(
        !dacl.is_null(),
        "Codewhale-owned xAI OAuth storage must have an owner-only DACL"
    );
    let mut count = 0;
    let mut entries: *mut EXPLICIT_ACCESS_W = std::ptr::null_mut();
    // SAFETY: `dacl` belongs to the live descriptor; Windows allocates the
    // returned entry array, released by the guard below.
    let result = unsafe { GetExplicitEntriesFromAclW(dacl, &mut count, &mut entries) };
    if result != ERROR_SUCCESS {
        return Err(std::io::Error::from_raw_os_error(result as i32))
            .context("reading Codewhale-owned xAI OAuth DACL entries");
    }
    let _entries = WindowsLocalAllocation(entries.cast());
    anyhow::ensure!(
        count == 1 && !entries.is_null(),
        "Codewhale-owned xAI OAuth DACL must grant only one user"
    );
    // SAFETY: `count == 1` proves the first returned entry is initialized.
    let entry = unsafe { &*entries };
    let trustee_sid: PSID = entry.Trustee.ptstrName.cast();
    anyhow::ensure!(
        entry.Trustee.TrusteeForm == TRUSTEE_IS_SID
            && !trustee_sid.is_null()
            && unsafe { EqualSid(trustee_sid, user.sid()) } != 0
            && matches!(entry.grfAccessMode, SET_ACCESS | GRANT_ACCESS)
            && entry.grfAccessPermissions == FILE_ALL_ACCESS,
        "Codewhale-owned xAI OAuth DACL is not current-user-only"
    );
    Ok(())
}

#[cfg(windows)]

View on GitHub (pinned to 8880682c63)

Solutions

  1. Recreate the credentials: delete the contents of $CODEWHALE_HOME/credentials and run codewhale auth xai-device
  2. Or normalize the ACL: icacls <path> /inheritance:r then icacls <path> /grant:r "%USERNAME%:(OI)(CI)F"
  3. Audit first with icacls <path> to see which extra entries exist

Example fix

:: before
icacls "%USERPROFILE%\.codewhale\credentials"   :: multiple ACEs

:: after
icacls "%USERPROFILE%\.codewhale\credentials" /inheritance:r
icacls "%USERPROFILE%\.codewhale\credentials" /grant:r "%USERNAME%:(OI)(CI)F"
Defensive patterns

Strategy: retry

Try / catch

match login() {
    Ok(v) => v,
    Err(e) if e.to_string().contains("DACL must grant only one user") => {
        reset_acl_to_owner_only(&credentials_dir)?; // icacls /inheritance:r + /grant:r user
        login()?
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Upgrading codewhale over credentials created by an older version without PROTECTED_DACL; icacls grants to groups or other users; inherited ACEs leaking from a permissive parent directory.

Common situations: Version upgrades tightening the security policy; shared machines where an admin granted another account access to the home directory.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16). Data as JSON: /api/errors/b24a078e95765c0d. Report an issue: GitHub.