macOS: keychain prompts on every launch when GitHub-signed and Microsoft-signed copilot binaries share login-keychain items (XARA partition mismatch)
- 主要语言
- 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