[BUG] Keychain credential partition_id silently resets to "apple-tool:" alone on ~5min cycle (macOS Tahoe 26.5, Claude Code 2.1.145)

Resolved 💬 4 comments Opened May 26, 2026 by eoash Closed Jul 2, 2026

Summary

The Claude Code-credentials macOS Keychain entry's partition_id ACL silently reverts to apple-tool: alone on a recurring ~5-minute cycle on macOS Tahoe 26.5. The credential data itself is not modified (cdat/mdat remain stable) — only the ACL changes. When this happens, new Claude Code sessions display Not logged in · Please run /login, even though the OAuth token is still valid in the keychain. Pressing /login re-creates the entry with the same broken ACL pattern, causing a self-reinforcing cycle.

Verified with 6 days of LaunchAgent monitoring (1,041 log entries, 101 regression samples) and an automated recovery workaround. Re-applying the correct partition_id list with security set-generic-password-partition-list instantly restores access without re-authentication — confirming this is purely an ACL mutation, not credential invalidation.

Environment

  • macOS: 26.5 (build 25F71) — Tahoe
  • Claude Code: 2.1.145 (installed at ~/.local/share/claude/versions/2.1.145)
  • Architecture: Apple Silicon (arm64)
  • Binary signing: unsigned (note the unsigned: token in the partition_id description below)

Symptom — Concrete Evidence

After /login, the keychain entry shows the expected 4-token partition_id:

$ security dump-keychain -a ~/Library/Keychains/login.keychain-db | \
    awk '/"svce".*"Claude Code-credentials"/,/^keychain:/' | grep -A1 partition_id
        authorizations (1): partition_id
        description: apple-tool:, apple:, teamid:Q6L2SF6YDW, unsigned:

Within ~5 minutes (without any user action), the same query returns:

        authorizations (1): partition_id
        description: apple-tool:

Three of the four tokens (apple:, teamid:Q6L2SF6YDW, unsigned:) silently disappear. The OAuth credential data itself is untouched — cdat and mdat timestamps remain identical to creation time.

Reproduction Steps

  1. Fresh macOS Tahoe 26.5 with Claude Code 2.1.145 installed and logged in via /login
  2. Use Claude Code normally for ~5–10 minutes (any background CLI activity)
  3. Inspect the keychain entry:

``bash
security dump-keychain -a ~/Library/Keychains/login.keychain-db | \
awk '/"svce".*"Claude Code-credentials"/,/^keychain:/' | grep -A1 partition_id
``

  1. Observe: description now shows apple-tool: alone (3 of 4 tokens removed)
  2. Open a new terminal → claudeNot logged in · Please run /login
  3. Restore with: security set-generic-password-partition-list -s "Claude Code-credentials" -a <user> -S "apple-tool:,apple:,teamid:Q6L2SF6YDW,unsigned:" -k <password> ~/Library/Keychains/login.keychain-db
  4. Access restored immediately, without re-authentication
  5. Regression recurs within ~5 minutes — confirmed across 101 samples

Frequency Data (LaunchAgent Polling, 5-min Interval)

From claude-auth-monitor.log on 2026-05-26:

08:25:20 REGRESSED  (Δ unknown)
08:30:59 REGRESSED  (Δ 5min 39s)
08:36:34 REGRESSED  (Δ 5min 35s)
08:42:13 REGRESSED  (Δ 5min 39s)
08:47:48 REGRESSED  (Δ 5min 35s)
08:55:08 REGRESSED  (Δ 7min 20s)
09:00:50 REGRESSED  (Δ 5min 42s)
...continues for hours...

Mean inter-regression interval (5/26): 12.7 minutes (52 samples). Floor of 232 seconds observed.

Hypotheses Tested and Ruled Out

| Hypothesis | Test | Result |
|---|---|---|
| Claude Code binary auto-update on disk triggers ACL reset | Set DISABLE_AUTOUPDATER=1 in ~/.claude/settings.json/env; verified binary unchanged at 2.1.145 since 5/20 | ❌ Regression continues unchanged |
| External event (sleep/wake, network, macOS security daemon) | Captured 104 environment snapshots at each regression; no consistent external trigger | ❌ No correlation |
| Credential being deleted and recreated (like #22144's 8h token refresh) | Verified cdat/mdat stable across regressions — entry data untouched | ❌ Only ACL changes, not data |

Cross-Correlation Analysis (Inflection Point Identified)

Comparing claude-auth-monitor.log (1,041 lines across 6 days) with softwareupdate --history and Claude binary timestamps:

| Date / Time | Event | Effect |
|---|---|---|
| 2026-05-20 11:03:28 | Claude Code 2.1.145 binary installed (last update; binary unchanged afterwards via DISABLE_AUTOUPDATER=1) | — |
| 2026-05-21 ~ 2026-05-24 | macOS 26.4.1 + Claude 2.1.145 (stable combination) | avg inter-regression interval: 304.9 min (~5 hours), 17 samples |
| 2026-05-25 23:21:05 | Last OK reading before macOS upgrade | — |
| 2026-05-25 23:23:40 | macOS Tahoe 26.5 installed (per softwareupdate --history) | 🚨 inflection point |
| 2026-05-25 23:30:38 | First regression after 26.5 install (7 minutes later) | — |
| 2026-05-26 | macOS 26.5 + Claude 2.1.145 (entire day) | avg inter-regression interval: 12.7 min, 52 samples |

Net effect: ~24× acceleration immediately after macOS 26.5 install. The Claude Code binary is byte-identical across this boundary (same 2.1.145, unchanged since 5/20). The only variable that changed at 5/25 23:23:40 is the macOS version. This is a controlled-variable observation pointing strongly at a behavior change in macOS 26.5's keychain ACL handling that interacts adversarially with an unsigned third-party CLI like Claude Code.

Independent confirmation: when we create a fresh generic password entry on macOS 26.5 via security add-generic-password -A ..., the new entry is automatically born with partition_id: apple-tool: alone — third-party CLI access blocked by default. This pattern was not observed on macOS 26.4.1.

Likely Root Cause (Speculation)

Because the credential data is unchanged but the ACL keeps getting clipped to apple-tool: alone on a tight cycle, the trigger appears to be a periodic operation in the Claude Code CLI itself (likely an OAuth token validity check or read) that, on an unsigned binary running under macOS 26.5's tightened keychain policy, causes the partition_id list to be re-evaluated and demoted. The macOS 26.5 cross-correlation above isolates the macOS-side change as the precipitating factor; the unsigned-binary state of Claude Code makes it the visible victim.

Related but Distinct Issues

  • #22144 (closed, not planned): Third-party tool friction from 8h token refresh wiping ACL entirely. Different mechanism — that's a credential delete/recreate cycle, not an ACL-only mutation.
  • #47321 (closed): Missing kSecUseDataProtectionKeychain flag causing prompts on binary signature changes. Different mechanism — code-signature dependent, not time-based.
  • #9403 (closed, not planned): Service-name read/write mismatch. Different mechanism.

This issue is specifically about an ACL-only, ~5-minute recurring partition_id reversion that emerged with macOS 26.5, which none of the above cover.

Workaround (Documented for Other Affected Users)

LaunchAgent that polls the keychain every 5 minutes and uses a chmod 600 plaintext password file to invoke security set-generic-password-partition-list when regression is detected. Sample log lines after the recovery loop was deployed:

2026-05-26 11:31:39 AUTO_RECOVERED (no user interaction)
2026-05-26 11:36:33 OK desc=apple-tool:, apple:, teamid:Q6L2SF6YDW, unsigned:
2026-05-26 11:41:48 OK ...

Mean recovery time: ~5 seconds. Full script and LaunchAgent plist available on request.

Asks (in Preference Order)

  1. Sign the Claude Code CLI binary with Anthropic's Developer ID Application certificate and have the post-install step register the team ID into the credential's partition_id list. This would make the ACL stable against macOS 26.x's automatic hardening.
  2. Have the CLI re-apply the correct partition_id list on each token access/refresh, so that even if macOS clips it back to apple-tool:, the next CLI operation re-populates the 4-token set.
  3. (Minimum) Document the manual security set-generic-password-partition-list workaround in the official troubleshooting guide, so users on macOS 26.x are not stuck in a /login → broken-ACL → re-/login cycle.

Additional Artifacts

Happy to provide on request:

  • Full 104-snapshot dump (sanitized) showing environment state at each regression
  • Complete claude-auth-monitor.log (1,041 lines, 6 days, 101 samples)
  • LaunchAgent plist and bash script source
  • Per-day regression count timeline (2 → 11 → 3 → 2 → 35 → 53 across 5/21–5/26)

View original on GitHub ↗

This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗