anthropics / anthropics/claude-code

[BUG] Claude Code fails to authenticate on MacOS in certain environments.

Ouverte
#88,024 1 commentaire 1 réaction 0 personnes assignées Voir sur GitHub
area:auth area:security bug has repro platform:macos
Langage dominant
Python
Étoiles
145k
Forks
23.1k
Métriques de merge des PR
Métriques de PR en attente

Description

### Preflight Checklist

- [x] I have searched [existing issues](https://github.com/anthropics/claude-code/issues?q=is%3Aissue%20state%3Aopen%20label%3Abug) and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code

### What's Wrong?

On macOS, Claude Code shells out to the `security` command for Keychain read/write operations (storing and retrieving OAuth credentials under the `Claude Code-credentials` service name) by invoking the bare command name `security`, resolved via the user's `$PATH`, rather than the absolute system path `/usr/bin/security`.

This has two consequences:

1. **Reliability:** In environments where `$PATH` has been modified (shell config, Homebrew shims, corporate MDM-managed shells, EDR/security tooling that wraps or intercepts common binary names), the resolved `security` may not be the Apple-signed system binary. This can produce silent failures, unexpected behavior, or interference from security tooling that pattern-matches on generic binary names rather than a known, fixed system path — surfacing to the end user as `Failed to retrieve auth status after login` with no actionable diagnostic.
2. **Security:** Resolving a security-sensitive credential-access binary via `$PATH` instead of an absolute path is a PATH-hijacking risk. Any writable directory earlier in `$PATH` than `/usr/bin` containing an executable named `security` would be invoked instead of the real system binary, with no warning. Absolute-pathing this is a standard hardening practice for any tool that shells out to a security-critical system binary.

### What Should Happen?

Claude Code should invoke `/usr/bin/security` explicitly for every macOS Keychain read/write operation. On a healthy system this changes nothing user-visible — identical behavior to today. On a compromised or interfered-with `$PATH`, this removes the ambiguity entirely: the binary invoked is always the real one, and any failure can be attributed to that specific, known binary rather than an unknown PATH-resolved substitute.

### Error Messages/Logs

```shell

```

### Steps to Reproduce

**Reproduction A — generic PATH-shadowing demo (doesn't require knowing the offending package):**

1. Create a fake `security` binary earlier in `$PATH` than `/usr/bin`:
```bash
mkdir -p ~/fake-bin
cat > ~/fake-bin/security << 'EOF'
#!/bin/bash
echo "FAKE SECURITY BINARY INVOKED: $@" >&2
exit 1
EOF
chmod +x ~/fake-bin/security
export PATH="$HOME/fake-bin:$PATH"
```
2. Confirm the shell now resolves the fake binary:
```bash
which security
# -> /Users//fake-bin/security (should be /usr/bin/security)
```
3. Launch Claude Code (or the IDE extension) from this shell session and attempt `/login`.
4. **Observed:** Claude Code fails to retrieve/store credentials — surfaces as `Failed to retrieve auth status after login` or `Auth token: none` — because it invoked the fake binary in step 1 instead of the real Keychain tool.
5. Clean up:
```bash
unset PATH # or open a new shell
rm -rf ~/fake-bin
```
6. **Fix verification:** manually forced Claude Code's Keychain calls to resolve `/usr/bin/security` explicitly instead of the `$PATH`-resolved `security` (tested by placing `/usr/bin` first in `$PATH` for the session / invoking the absolute path directly in the credential helper). With `/usr/bin/security` used explicitly, `/login` and `/status` succeeded immediately and consistently — no EDR kill, no `Failed to retrieve auth status after login`, no further auth errors. Reverting to PATH-resolved `security` reproduced the failure again immediately. This isolates the root cause conclusively: **the bug is the unqualified `security` invocation, not the EDR, not the entitlement flag, not the Keychain ACL.**

**Reproduction B — actual field case (EDR-interfered `security`):**

1. On a managed macOS endpoint with EDR software installed (SentinelOne in this case), run:
```bash
security find-generic-password -a "$USER" -s "Claude Code-credentials" -w
echo "exit code: $?"
```
2. **Observed:** process is killed before returning (`Killed: 9` / SIGKILL) rather than returning the credential or a normal permission error.
3. Attempt `/login` in Claude Code IDE extension.
4. **Observed:** `Failed to retrieve auth status after login`, reproducible on every login attempt on this endpoint.
5. Confirming it's a PATH resolution issue, not solely an EDR issue: `which -a security` on the affected endpoint to check for multiple resolvable `security` binaries in `$PATH` ahead of `/usr/bin/security`. (We could not identify which installed package placed the additional binary on `$PATH` — see note below.)
6. **Fix verification:** manually forced Claude Code's Keychain calls to resolve `/usr/bin/security` explicitly instead of the `$PATH`-resolved `security` (tested by placing `/usr/bin` first in `$PATH` for the session / invoking the absolute path directly in the credential helper). With `/usr/bin/security` used explicitly, `/login` and `/status` succeeded immediately and consistently — no EDR kill, no `Failed to retrieve auth status after login`, no further auth errors. Reverting to PATH-resolved `security` reproduced the failure again immediately. This isolates the root cause conclusively: **the bug is the unqualified `security` invocation, not the EDR, not the entitlement flag, not the Keychain ACL.**

**Note on root cause of the shadow binary:** In our case, something in the environment (suspected but unconfirmed: a Python package installed via `pip` that ships or symlinks a same-named `security` CLI) placed an executable named `security` on `$PATH` ahead of `/usr/bin`. We were not able to pin down the exact package. This doesn't change the fix — regardless of *what* shadows `security`, hardcoding `/usr/bin/security` closes the gap. Anyone hitting this can self-diagnose with:
```bash
which -a security
```
which lists every `security` binary resolvable on `$PATH`, in resolution order.

### Claude Model

None

### Is this a regression?

I don't know

### Last Working Version

_No response_

### Claude Code Version

2.1.235 (Claude Code)

### Platform

Anthropic API

### Operating System

macOS

### Terminal/Shell

iTerm2

### Additional Information

## Proposed fix

Replace all invocations of security in the macOS Keychain integration with the absolute path /usr/bin/security. This is the fixed, standard location on all supported macOS versions (System Integrity Protection prevents this path from being altered or removed), so there's no portability tradeoff.

Example of the class of call that needs updating:

bash
# Current (PATH-resolved, ambiguous)
security find-generic-password -a "$USER" -s "Claude Code-credentials" -w

# Should be (absolute path, unambiguous)
/usr/bin/security find-generic-password -a "$USER" -s "Claude Code-credentials" -w

## Why this matters beyond convenience

This surfaced during troubleshooting of `Failed to retrieve auth status after login` on a managed macOS fleet where EDR software was interfering with `security` invocations. Root-causing was harder than necessary because there was no way to confirm which `security` binary was actually being invoked. Absolute-pathing doesn't fix EDR/AV false positives on its own, but it removes an entire class of PATH-related ambiguity and closes a real (if narrow) hijacking vector — should be treated as a security hardening fix, not just a bug fix.

## Related issues

- #51971 — same user-facing error text, different root cause (Pro/Console entitlement conflict)
- #81707 — same error family, root cause is Keychain ACL partition-list corruption on write

Neither of those is caused by the `$PATH` resolution issue described here, but all three currently surface the same generic auth failure to the user with no way to distinguish cause. Fixing this doesn't resolve #51971 or #81707, but removes one more variable from that failure mode and hardens the credential path.

## Environment

Guide de contribution

Aucun guide de contribution indexé pour ce dépôt

Piste de recherche

Search the repository for the macOS Keychain integration and every invocation of the `security` command; the issue does not name specific files or tests. Reproduce the PATH-shadowing setup, then verify that `/login` and `/status` succeed when the system binary is selected explicitly and that all relevant credential operations use that path.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
macos, python, shell
Domaine
authentication, cli, security
Type d'issue
Bug
Difficulté
3/5
Temps estimé
1-2 jours
Activité
Active
Clarté
Plutôt claire
Accessibilité débutants
68/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.