Enterprise MCP registry unreachable on macOS: rustls rejects private CA cert (Apple -67901), fail-closed blocks all MCP
- Lingua principale
- Shell
- Stelle
- 11.2k
- Fork
- 1.9k
- Merge medio
- 14h 16m
- PR unite (30g)
- 6
Descrizione
## Describe the bug
On macOS, Copilot CLI **1.0.78** fails to validate MCP servers against an enterprise custom MCP registry because TLS verification rejects the registry's private-CA certificate with Apple error **-67901** (`certificate is not standards compliant`).
The CLI then treats the registry as **unreachable** and **fail-closes**: all non-default / custom MCP servers are reported as **blocked by policy**, even though:
- the registry is reachable over HTTPS from the same machine (`curl` / Node `fetch` return HTTP 200)
- Chrome trusts and displays the certificate without issue
- the same servers are listed in the enterprise registry and were usable with an earlier CLI version (allowlist check previously went through the Node/JS path)
This looks like a regression from moving the MCP registry allowlist HTTP client into the Rust runtime (`reqwest` + `rustls-platform-verifier` / Apple Security.framework), which applies stricter Apple TLS rules than Node/Chrome.
## Affected version
- GitHub Copilot CLI **1.0.78** (auto-updated ~2026-08-03 / 2026-08-04)
- macOS **26.x** (Apple Silicon)
- Enterprise / org Copilot policy: custom **MCP Registry URL** + **Registry only** allowlist
Previously worked on an earlier 1.x CLI where registry allowlist verification still lived in the JS/`app.js` path (Node TLS). After 1.0.78, the same check appears in the native runtime (`rustls_platform_verifier::verification::apple`) and fails.
## Steps to reproduce
1. Configure an org/enterprise Copilot MCP registry URL pointing at an internal HTTPS registry (private PKI), with **Restrict MCP access to registry servers = Registry only**.
2. Add one or more registry-listed MCP servers to `~/.copilot/mcp-config.json` (or via `/mcp add`).
3. Start Copilot CLI with `--log-level debug` (or run `/mcp reload`).
4. Observe custom MCP servers blocked by policy.
## Expected behavior
- Registry HTTPS fetch should succeed for a certificate that the OS / Chrome / Node already trust for that host, **or**
- If Apple TLS policy rejects the leaf (e.g. validity period), the CLI should surface a **clear TLS/certificate error** (not a generic “blocked by policy”), and ideally provide a documented enterprise path (fail-open option, private-CA guidance, or less strict verification for admin-configured registry URLs).
## Actual behavior
User-facing:
```text
! 3 MCP servers were blocked by policy: '', '', ''
```
Debug log (redacted host):
```text
[DEBUG] Registry https:///: servers will be verified against this registry
[DEBUG] starting new connection 'Some("")'
[ERROR] failed to verify TLS certificate: invalid peer certificate: Other(OtherError("“*.” certificate is not standards compliant: -67901"))
log.target=rustls_platform_verifier::verification::apple
[DEBUG] Registry https:/// unreachable when checking server "" after 3 attempts:
error sending request for url (https:///v0.1/servers//versions/latest)
[ERROR] MCP server "" filtered: Registry https:/// was unreachable
```
Telemetry kinds observed: `mcp_policy_check`, `mcp_allowlist_policy_check`.
Same host from the same machine:
- `curl` → TLS OK, HTTP 200 on `/v0/servers` and `/v0.1/servers`
- Node `fetch` → OK
- Chrome certificate viewer → trusts leaf issued by internal CA
## Certificate details (redacted)
- Subject CN / SAN: `*.`
- Issuer: internal enterprise PKI (private CA)
- Validity window: **~1095 days** (issued Jan 2026 → expires Jan 2029)
- Apple trusted-certificate guidance requires leaf validity **≤ 825 days** for certs issued after 2019 — this is the likely trigger for `-67901` / “not standards compliant”
- Fingerprint available privately if needed; hostnames intentionally redacted
## Additional context / analysis
Local package comparison on disk:
| CLI package | Allowlist / registry verify strings | TLS stack for that check |
|---|---|---|
| 1.0.58 / 1.0.59 / 1.0.61 | Present in `app.js` | Node |
| 1.0.78 | Present in `runtime.node`, removed from `app.js` | Rust + `rustls_platform_verifier` (Apple) |
So this is not “registry down” and not (yet) an identity fingerprint mismatch (`does not match the registered server identity`). The allowlist never reaches a successful registry HTTP response.
Related but distinct issues: #2481 / #2498 (policy fetch 404), #3934 (identity mismatch), #4346 (403 in CI). This report is specifically **TLS verification of the enterprise registry URL on macOS after the Rust migration**.
## Asks
1. Confirm whether enterprise MCP registry fetches are intentionally pinned to `rustls-platform-verifier` on macOS.
2. Improve error UX: distinguish **TLS/cert rejection** from **policy deny** / true unreachability.
3. Consider enterprise-friendly options: honor OS trust more like Chrome for admin-configured registry URLs, document Apple 825-day constraint for private PKI, or provide a supported workaround short of reissuing certs / switching policy to Allow all.
4. Optionally fail-open (or cache last-good registry allowlist) when the configured registry URL fails TLS, similar to other managed-settings fail-open work in 1.0.78 — today MCP custom servers are hard-blocked.
Happy to provide more info if needed!
Guida per i contributori
Apri la guida per i contributori
Direzione di ricerca
Confronta i percorsi di verifica del registro in app.js e runtime.node, quindi traccia l’errore macOS attraverso rustls_platform_verifier::verification::apple. Riproduci il caso di una CA privata con il logging di debug e distingui il rifiuto del certificato dal diniego dovuto ai criteri; il lavoro è completato quando l’errore viene esposto accuratamente e qualsiasi gestione aziendale supportata è documentata o coperta dal design scelto per l’issue.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- macos, node.js, rust
- Ambito
- cli, networking, security
- Tipo di issue
- Bug
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Stato di attività
- Tranquilla
- Chiarezza
- Abbastanza chiara
- Idoneità per principianti
- 42/100