github / github/copilot-cli

macOS: keychain prompts on every launch when GitHub-signed and Microsoft-signed copilot binaries share login-keychain items (XARA partition mismatch)

未关闭
#4,273 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看
area:authentication
主要语言
Shell
星标
11.2k
派生
1.9k
平均合并
14 小时 16 分钟
30 天内合并 PR
6

描述

### Describe the bug

On macOS, `copilot` stores credentials in legacy login-keychain items (`copilot-cli`, `copilot-mcp-oauth`). macOS XARA protection scopes each item's ACL to a *partition list* containing the Team ID of whoever last wrote it.

The same CLI ships under two different Developer ID Team IDs:

| Path | `Identifier` | Team ID |
|---|---|---|
| `~/Library/Caches/github-copilot-sdk/cli//copilot` | `copilot` | `VEKTX9H2N7` (GitHub, Inc.) |
| `/Applications/Microsoft Scout.app/Contents/Resources/app.asar.unpacked/node_modules/@github/copilot-darwin-arm64/copilot.app` | `com.microsoft.clawpilot.copilot` | `UBF8T346G9` (Microsoft) |

Both read and write the same items, so each one invalidates the other's approval. "Always Allow" never sticks and the user is prompted forever.

From `log show --predicate 'process == "securityd"'`:

```
09:08:23 ACL partition mismatch: client teamid:VEKTX9H2N7 ACL ("teamid:UBF8T346G9")
09:08:23 asking user about XARA partition for 'teamid:VEKTX9H2N7'
09:08:23 displaying keychain prompt for .../github-copilot-sdk/cli/1.0.73/copilot
09:08:30 user approved 'always allow' -> adding XARA partition 'teamid:VEKTX9H2N7'
09:08:41 ACL partition mismatch: client teamid:UBF8T346G9 ACL ("teamid:VEKTX9H2N7")
09:08:41 displaying keychain prompt for /Applications/Microsoft Scout.app/.../copilot.app
09:47:18 ACL partition mismatch: client teamid:UBF8T346G9 ACL ("teamid:VEKTX9H2N7")
10:03:28 ACL partition mismatch: client teamid:VEKTX9H2N7 ACL ("teamid:UBF8T346G9")
```

Signature confirmation:

```
$ codesign -dv --verbose=2 ~/Library/Caches/github-copilot-sdk/cli/1.0.73/copilot
Identifier=copilot
Authority=Developer ID Application: GitHub (VEKTX9H2N7)
TeamIdentifier=VEKTX9H2N7

$ codesign -dv --verbose=2 "/Applications/Microsoft Scout.app/Contents/Resources/app.asar.unpacked/node_modules/@github/copilot-darwin-arm64/copilot.app"
Identifier=com.microsoft.clawpilot.copilot
Authority=Developer ID Application: Microsoft Corporation (UBF8T346G9)
TeamIdentifier=UBF8T346G9
```

**Amplified by an orphaned-item leak.** My login keychain held **765** `copilot-mcp-oauth` items against **8** files in `~/.copilot/mcp-oauth-config/`, so **757 were orphans**. Creation timestamps show a new batch on every launch:

| Month | Items created |
|---|---|
| Feb-Apr 2026 | 10 |
| May 2026 | 138 |
| Jun 2026 | 364 |
| Jul 2026 (27 days) | 253 |

Three launches on 2026-07-27 produced 10 new items (6 at `15:47:43Z`, 3 at `16:08:35Z`, 1 at `17:03:34Z`), none of which matched a config file -- orphaned on creation. Each orphan is born with a single-Team-ID partition list, so each is a latent prompt.

This overlaps #2112, which diagnoses the stale-entry half on Windows/keytar. The macOS partition-list collision looks separate and unfiled.

### Affected version

`GitHub Copilot CLI 1.0.75` (Scout-embedded) and `1.0.73` (SDK cache).

### Steps to reproduce the behavior

1. On macOS, use a host that embeds the GitHub-signed CLI (e.g. the Copilot app, via `github-copilot-sdk`).
2. Also use a host that embeds a Microsoft-signed copy (Microsoft Scout).
3. Sign in and configure at least one OAuth-based MCP server.
4. Launch each app in turn. Approve "Always Allow" when prompted.
5. Prompts return on the next launch of the other app, indefinitely.

### Expected behavior

Approving "Always Allow" once should be durable. Concretely:

1. When creating keychain items, set a partition list trusting every Team ID the CLI ships under (`teamid:VEKTX9H2N7,teamid:UBF8T346G9`) rather than letting macOS default to the writing binary's own Team ID.
2. Reuse the existing `copilot-mcp-oauth` item for a given server instead of writing a freshly-hashed one per launch, and delete the entry it supersedes.
3. Consider the data-protection keychain (`kSecUseDataProtectionKeychain` plus a shared access group) instead of the legacy file keychain, which sidesteps XARA partition lists entirely.

### Additional context

- **OS:** macOS 26.5.2 (25F84)
- **CPU:** arm64 (Apple silicon)
- **Shell:** zsh

Manual workaround -- trust both Team IDs. This is one-time and resets whenever an item is recreated:

```bash
security set-generic-password-partition-list \
-S teamid:VEKTX9H2N7,teamid:UBF8T346G9,apple-tool:,apple: \
-s copilot-cli ~/Library/Keychains/login.keychain-db

security set-generic-password-partition-list \
-S teamid:VEKTX9H2N7,teamid:UBF8T346G9,apple-tool:,apple: \
-s copilot-mcp-oauth ~/Library/Keychains/login.keychain-db
```

Orphans can be identified by diffing keychain account names against `~/.copilot/mcp-oauth-config/*.json` basenames:

```bash
security dump-keychain ~/Library/Keychains/login.keychain-db | awk '
/^keychain:/ { acct="" }
/"acct"=/ { l=$0; sub(/^.*"acct"="/,"",l); sub(/".*$/,"",l); acct=l }
/"svce"="copilot-mcp-oauth"/ { print acct }' | sort -u
```

Deleting the 757 orphans is safe and requires no keychain authorization (deletion does not decrypt the item, so it produces no prompt).

贡献指南

打开贡献指南

调研方向

首先定位与 `copilot-cli`、`copilot-mcp-oauth` 和 `~/.copilot/mcp-oauth-config/*.json` 相关的钥匙串项目创建路径和 OAuth 配置路径。使用两个已签名二进制文件交替启动,复现该过程,并使用提供的 `security` 命令检查生成的项目。完成的标准是:两个 Team IDs 都能保持持久授权,复用服务器现有的项目,并且没有新创建的孤立条目。

由索引模型根据 Issue 内容生成。

评估

技术栈
macos, shell
领域
authentication, security
Issue 类型
缺陷
难度
5/5
预计耗时
一周以上
活跃度
冷清
描述清晰度
基本清楚
新手友好度
35/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。