Skip to content

GitHub Copilot CLI fails with "fetch failed" error in corporate environments with SSL inspection #333

@lucascury-fl

Description

@lucascury-fl

Describe the bug

GitHub Copilot CLI fails to connect in corporate environments that use SSL inspection/man-in-the-middle proxies, even when corporate certificates are properly installed in the macOS System keychain. The issue manifests differently depending on how the CLI is used:

  • Interactive mode (npx @github/copilot): Shows vague "✗ Execution failed: fetch failed" error message
  • Command mode (npx @github/copilot -p "prompt"): Hangs indefinitely and never completes

The root cause is that Node.js is unable to get issuer certificate. Also, the --use-system-ca flag only reads from /System/Library/Keychains/SystemRootCertificates.keychain, but corporate certificates are typically stored in /Library/Keychains/System.keychain, causing certificate verification failures.

Bottom line: There's currently no debug logging or documentation available to troubleshoot or infer that this SSL interception is causing the problem (silent issue).

Affected version

0.0.342 Commit: 69ac520

Steps to reproduce the behavior

  1. Be in a corporate environment with SSL inspection/man-in-the-middle proxy (e.g. GlobalProtect, no proxy configured at the local machine)

  2. Ensure corporate certificates are installed in macOS System keychain (not the SystemRootCertificates.keychain)

$ security find-certificate -c "ssl.corporate.com" /Library/Keychains/System.keychain
  1. Install GitHub Copilot CLI:
$ npm install -g @github/copilot

Test interactive mode:

  1. Start interactive mode:
$ copilot --log-level debug
  1. If prompted for authentication, follow the on-screen instructions to complete GitHub login (open browser, enter device code, authorize)
/login
> 1. GitHub.com
...Waiting for authorization
Enter one-time code: ABCD-1234 at https://github.com/login/device
<Enter>
 Login to GitHub and confirm the one-time code in the browser window

  1. Wait for the CLI to load and show the interactive prompt, and try to submit any prompt :
> Say Hello via CLI Interactive Mode!
  1. 🛑 Observe: Error message appears
✗ Execution failed: fetch failed

Test non-interactive/command mode:

  1. Try running a command with the -p parameter:
$ copilot -p "Say Hello via CLI Command" --log-level debug
  1. 🛑 Observe: Command hangs indefinitely and never returns (tested for 5+ minutes)

  2. Press Ctrl+C to cancel the hanging command

Expected behavior

Overview:
GitHub Copilot CLI should work seamlessly in corporate environments when corporate certificates are properly installed in the system keychain, similar to how web browsers and other applications handle corporate SSL inspection.

Both interactive mode and command mode should function normally without requiring manual certificate configuration.

Impact:
This issue affects any organization using SSL inspection for security compliance, making GitHub Copilot CLI completely unusable in enterprise environments without manual workarounds. The different symptoms between interactive and command modes make troubleshooting particularly challenging.

Suggested "solutions":

  1. Improve documentation (both online and within CLI to bring awareness this known challenge/limitation; I've spent a couple of painful hours to troubleshoot this one, but we could prevent that for others 😉)
  2. Document NODE_EXTRA_CA_CERTS workaround in a troubleshooting guide
  3. Better error handling and improved debug logging that could capture meaningful logging for this "edge case" on corporate environment.
  4. Possibly add --ca-bundle CLI option for custom certificates or something similar

Additional context

Environment Details:

  • OS: macOS 26.0.1 (25A362) (tested on Apple Silicon M3 Pro)
  • Node.js: v24.9.0
  • Shell: zsh

Debug Logging:

Error logs from ~/.copilot/logs/:

  1. Interactive Mode
2025-10-16T17:35:02.714Z [LOG] Using Copilot API endpoint: https://api.business.githubcopilot.com/mcp/readonly
2025-10-16T17:35:02.716Z [LOG] Starting remote MCP client for github-mcp-server with url: https://api.business.githubcopilot.com/mcp/readonly
2025-10-16T17:35:02.716Z [LOG] Creating MCP client for github-mcp-server...
2025-10-16T17:35:02.721Z [LOG] Connecting MCP client for github-mcp-server...
2025-10-16T17:35:02.901Z [LOG] MCP transport for github-mcp-server closed
2025-10-16T17:35:02.901Z [LOG] GitHub MCP server configured after authentication
2025-10-16T17:35:03.086Z [DEBUG] Creating copilot-client for integration ID copilot-developer-cli with token authentication. User-agent: copilot/0.0.342 (darwin v24.9.0) OpenAI/5.20.1
2025-10-16T17:35:28.898Z [DEBUG] Detected mentions: 
2025-10-16T17:35:29.091Z [DEBUG] Using model: claude-sonnet-4.5
2025-10-16T17:35:29.091Z [START-GROUP] configured settings:
2025-10-16T17:35:29.091Z [DEBUG] {
  "version": "latest",
  "service": {
    "instance": {
      "id": "267d5801-6d54-4c4d-9ba6-d635fe0a05fa"
    },
    "agent": {
      "model": "sweagent-capi:claude-sonnet-4.5"
    }
  },
  "blackbird": {
    "mode": "initial-search"
  },
  "problem": {
    "statement": "Say Hello via CLI Interactive Mode!"
  },
  "api": {
    "copilot": {
      "url": "https://api.business.githubcopilot.com",
      "integrationId": "copilot-developer-cli",
      "token": "******"
    }
  },
  "github": {
    "repo": {
      "name": "temp-repo",
      "commit": "temp-commit",
      "readWrite": false
    }
  }
}
2025-10-16T17:35:29.091Z [END-GROUP] 
2025-10-16T17:35:29.092Z [DEBUG] Using Copilot API at https://api.business.githubcopilot.com with integration ID copilot-developer-cli
2025-10-16T17:35:29.092Z [DEBUG] Using GitHub OAuth token for Copilot API
2025-10-16T17:35:29.092Z [DEBUG] Creating copilot-client for integration ID copilot-developer-cli with token authentication. User-agent: copilot/0.0.342 (darwin v24.9.0) OpenAI/5.20.1
2025-10-16T17:35:29.093Z [DEBUG] str_replace_editor: default options: {
  "truncateBasedOn": "tokenCount",
  "truncateStyle": "middle"
}
2025-10-16T17:35:29.227Z [DEBUG] Command threw error: fetch failed
TypeError: fetch failed
    at file:///Users/<username>/.npm-global/lib/node_modules/@github/copilot/index.js:722:6766
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
    at async t.listModels (file:///Users/<username>/.npm-global/lib/node_modules/@github/copilot/index.js:1810:27762)
    at async I2e.getModel (file:///Users/<username>/.npm-global/lib/node_modules/@github/copilot/index.js:1812:12763)
    at async file:///Users/<username>/.npm-global/lib/node_modules/@github/copilot/index.js:1812:1171
    at async Uie.getCompletionWithTools (file:///Users/<username>/.npm-global/lib/node_modules/@github/copilot/index.js:1813:1029)
    at async t.getCompletionWithTools (file:///Users/<username>/.npm-global/lib/node_modules/@github/copilot/index.js:2348:54581)
    at async axn (file:///Users/<username>/.npm-global/lib/node_modules/@github/copilot/index.js:2372:14874)
    at async Gsl (file:///Users/<username>/.npm-global/lib/node_modules/@github/copilot/index.js:2372:12487)
  1. Command Mode
2025-10-16T17:40:01.943Z [DEBUG] Creating copilot-client for integration ID copilot-developer-cli with token authentication. User-agent: copilot/0.0.342 (darwin v24.9.0) OpenAI/5.20.1

SSL Debug verification:

  1. Verify corporate SSL inspection is active (shows corporate CA instead of public CA):
$ openssl s_client -connect api.business.githubcopilot.com:443 -servername api.business.githubcopilot.com -showcerts < /dev/null 2>/dev/null | openssl x509 -noout -issuer
issuer=C=US, ST=TX, L=A, O=Corporate, OU=IST, CN=ssl.corporate.com
  1. Verify Node.js certificate issue:
$ node --use-system-ca -e "require('https').get('https://api.business.githubcopilot.com/mcp/readonly', res => console.log('OK'))"
node:events:486
      throw er; // Unhandled 'error' event
      ^

Error: unable to get issuer certificate
    at TLSSocket.onConnectSecure (node:_tls_wrap:1631:34)
    at TLSSocket.emit (node:events:508:28)
    at TLSSocket._finishInit (node:_tls_wrap:1077:8)
    at ssl.onhandshakedone (node:_tls_wrap:863:12)
Emitted 'error' event on ClientRequest instance at:
    at emitErrorEvent (node:_http_client:107:11)
    at TLSSocket.socketErrorListener (node:_http_client:574:5)
    at TLSSocket.emit (node:events:508:28)
    at emitErrorNT (node:internal/streams/destroy:170:8)
    at emitErrorCloseNT (node:internal/streams/destroy:129:3)
    at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {
  code: 'UNABLE_TO_GET_ISSUER_CERT'
}

Node.js v24.9.0

SSL - Noteworthy:

  • The corporate certificates ARE in the system - but they're generally in [System.keychain], not in the root certificates keychain
  • The --use-system-ca flag for Node only looks in [SystemRootCertificates.keychain] (the standard root CAs), hence still leading to an issue, and not a feasible solution.

Current workaround:

# Export corporate certificates from System keychain 
mkdir ~/.ssl
security find-certificate -a -p /Library/Keychains/System.keychain > ~/.ssl/ca-bundle.pem
chmod +x ~/.ssl/ca-bundle.pem

# Add to your shell profile
echo 'export NODE_EXTRA_CA_CERTS="$HOME/.ssl/ca-bundle.pem"' >> ~/.zshrc

# Restart Terminal session and use with CLI

Note: If this temporary solution has to be around for a longer period of time, it might be a good idea to include the export of certificates step in your shell profile

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions