Phase 12/13 — Security Surface

Phase 12: Security Surface Analysis

Scope

Analysis date: 2026-03-12
Scope: copilot-sdk repository — Node.js, Python, Go, and .NET SDK clients
Purpose: Documentation of existing security-relevant behaviors; no recommendations included.

1. Authentication Model

The SDK supports four authentication methods, documented in docs/auth/index.md. They are applied in a strict priority order.

1.1 Authentication Priority Chain

As stated in docs/auth/index.md:269-278:

Priority Method Trigger
1 Explicit githubToken Token passed to SDK constructor
2 HMAC key CAPI_HMAC_KEY or COPILOT_HMAC_KEY env vars
3 Direct API token GITHUB_COPILOT_API_TOKEN + COPILOT_API_URL
4 Environment variable tokens COPILOT_GITHUB_TOKEN then GH_TOKEN then GITHUB_TOKEN
5 Stored OAuth credentials From previous copilot CLI login
6 GitHub CLI auth gh auth credentials

1.2 GitHub Signed-in User (Default)

The default path. Users authenticate via GitHub OAuth device flow. Credentials are stored in the system keychain by the CLI. The SDK reads these stored credentials automatically when no explicit token is provided (docs/auth/index.md:14-22).

All four SDKs create a client with no arguments to use this path:

  • TypeScript new CopilotClient()nodejs/src/client.ts:229
  • Python CopilotClient()python/copilot/client.py:126
  • Go copilot.NewClient(nil)go/client.go:106
  • .NET new CopilotClient()dotnet/src/Client.cs:103

1.3 OAuth GitHub App

Users authorize an OAuth app; the app receives a user access token (gho_ or ghu_ prefix) and passes it to the SDK via githubToken. Supported token prefixes are documented in docs/auth/index.md:192-198:

  • gho_ — OAuth user access tokens
  • ghu_ — GitHub App user access tokens
  • github_pat_ — Fine-grained personal access tokens
  • ghp_ — Classic personal access tokens (NOT supported, deprecated)

1.4 Environment Variable Tokens

For CI/CD and server-to-server. The SDK auto-detects tokens from environment variables in this order (docs/auth/index.md:209-213):

  1. COPILOT_GITHUB_TOKEN
  2. GH_TOKEN
  3. GITHUB_TOKEN

1.5 BYOK (Bring Your Own Key)

Bypasses GitHub Copilot authentication entirely. API keys from OpenAI, Azure AI Foundry, Anthropic, or compatible endpoints are passed directly in the session config. See Section 9 for full details.

1.6 Auth Validation When Using External Server

All four SDKs enforce that githubToken and useLoggedInUser cannot be combined with cliUrl. When cliUrl is set, the external CLI server manages its own auth:

  • TypeScript nodejs/src/client.ts:215-219 — throws Error
  • Python python/copilot/client.py:144-150 — raises ValueError
  • Go go/client.go:144-146 — calls panic()
  • .NET dotnet/src/Client.cs:133-136 — throws ArgumentException

1.7 HMAC Authentication

The auth types system includes an "hmac" auth type, referenced in:

  • nodejs/src/types.ts:977authType?: "user" | "env" | "gh-cli" | "hmac" | "api-key" | "token"
  • dotnet/src/Types.cs:1689 — Enum documentation for "hmac" variant

HMAC keys are read from CAPI_HMAC_KEY or COPILOT_HMAC_KEY environment variables (docs/auth/index.md:274). This is priority 2 in the auth chain, just below explicit githubToken.

1.8 Auth Status API

All SDKs expose a method to query authentication status via the auth.getStatus JSON-RPC call:

  • TypeScript getAuthStatus()nodejs/src/client.ts:775-781
  • Python get_auth_status()python/copilot/client.py:896-915
  • Go GetAuthStatus(ctx)go/client.go:1053-1064
  • .NET GetAuthStatusAsync(ct)dotnet/src/Client.cs:638-643

2. Token / Credential Handling

2.1 Token Flow: SDK to CLI

When a githubToken is provided to the SDK constructor, it is passed to the CLI subprocess via an environment variable, not via command-line arguments. The pattern is identical across all four SDKs:

  1. The SDK passes --auth-token-env COPILOT_SDK_AUTH_TOKEN as a CLI argument, telling the CLI to read the token from that env var.
  2. The SDK sets COPILOT_SDK_AUTH_TOKEN in the subprocess environment to the token value.

This avoids the token appearing in ps or /proc/*/cmdline output.

Citations:

// nodejs/src/client.ts:1126-1139
args.push("--auth-token-env", "COPILOT_SDK_AUTH_TOKEN");
// ...
envWithoutNodeDebug.COPILOT_SDK_AUTH_TOKEN = this.options.githubToken;
# python/copilot/client.py:1300-1322
args.extend(["--auth-token-env", "COPILOT_SDK_AUTH_TOKEN"])
# ...
env["COPILOT_SDK_AUTH_TOKEN"] = self.options["github_token"]
// go/client.go:1174-1210
args = append(args, "--auth-token-env", "COPILOT_SDK_AUTH_TOKEN")
// ...
c.process.Env = append(c.process.Env, "COPILOT_SDK_AUTH_TOKEN="+c.options.GitHubToken)
// dotnet/src/Client.cs:1023-1064
args.AddRange(["--auth-token-env", "COPILOT_SDK_AUTH_TOKEN"]);
// ...
startInfo.Environment["COPILOT_SDK_AUTH_TOKEN"] = options.GitHubToken;

2.2 Token Storage in SDK Memory

The githubToken is stored as a field on the client options object for the lifetime of the client:

  • TypeScript nodejs/src/client.ts:151githubToken?: string in the private options field
  • Python python/copilot/client.py:201-202self.options["github_token"] = github_token
  • Go go/client.go:188-189opts.GitHubToken = options.GitHubToken
  • .NET dotnet/src/Client.cs:1064 — set during StartCliServerAsync

The token lives in process memory; none of the SDKs persist it to disk.

2.3 Auto-Login Suppression

When a githubToken is explicitly provided, all SDKs default useLoggedInUser to false, which causes --no-auto-login to be passed to the CLI:

  • TypeScript nodejs/src/client.ts:249-250
  • Python python/copilot/client.py:179-183
  • Go go/client.go:1178-1186
  • .NET dotnet/src/Client.cs:1029-1033

2.4 Environment Variable Inheritance

The CLI subprocess inherits the parent process's environment by default (filtered):

  • TypeScript nodejs/src/client.ts:247env: options.env ?? process.env, then NODE_DEBUG is deleted (nodejs/src/client.ts:1134-1135)
  • Python python/copilot/client.py:1314-1318env = dict(os.environ) if not overridden
  • Go go/client.go:199-201opts.Env = os.Environ() if not set
  • .NET dotnet/src/Client.cs:1050-1059 — uses ProcessStartInfo.Environment, removes NODE_DEBUG

All SDKs allow overriding the environment via env/Environment options, giving callers full control over what the CLI subprocess sees.

3. Permission System

The SDK implements a permission request/response system that mediates CLI requests for potentially sensitive operations (tool invocations, file access, etc.).

3.1 Mandatory Permission Handler

All four SDKs require an onPermissionRequest handler when creating or resuming a session. Attempting to create a session without one results in an error:

// nodejs/src/client.ts:540-543
if (!config?.onPermissionRequest) {
    throw new Error("An onPermissionRequest handler is required ...");
}
# python/copilot/client.py:487-491
if not cfg.get("on_permission_request"):
    raise ValueError("An on_permission_request handler is required ...")
// go/client.go:488-489
if config == nil || config.OnPermissionRequest == nil {
    return nil, fmt.Errorf("an OnPermissionRequest handler is required ...")
}
// dotnet/src/Client.cs:389-393
if (config.OnPermissionRequest == null)
    throw new ArgumentException("An OnPermissionRequest handler is required ...");

3.2 Permission Request Result Kinds

The permission system supports four result kinds, defined across all SDKs:

Kind String Value Meaning
Approved "approved" Permission granted
Denied by Rules "denied-by-rules" Denied by policy/rules
Denied (No User) "denied-no-approval-rule-and-could-not-request-from-user" Cannot ask user
Denied by User "denied-interactively-by-user" User explicitly denied

Reference: go/types.go:110-125, dotnet/src/Types.cs:270-336, nodejs/src/types.ts:243

3.3 Pre-Built Permission Handlers

Each SDK provides an approveAll / ApproveAll convenience handler that approves every request:

// nodejs/src/types.ts:251
export const approveAll: PermissionHandler = () => ({ kind: "approved" });
// go/permissions.go:4-11
var PermissionHandler = struct {
    ApproveAll PermissionHandlerFunc
}{
    ApproveAll: func(_ PermissionRequest, _ PermissionInvocation) (PermissionRequestResult, error) {
        return PermissionRequestResult{Kind: PermissionRequestResultKindApproved}, nil
    },
}
// dotnet/src/PermissionHandlers.cs:8-12
public static class PermissionHandler
{
    public static PermissionRequestHandler ApproveAll { get; } =
        (_, _) => Task.FromResult(new PermissionRequestResult { Kind = PermissionRequestResultKind.Approved });
}

3.4 Permission Protocol Versions

The SDK supports two protocol versions for permission handling:

  • Protocol v2: The CLI sends permission.request RPC calls. The SDK registers a handler for these:
    • TypeScript nodejs/src/client.ts:1387-1391
    • Python python/copilot/client.py:1434
    • Go go/client.go:1365
    • .NET dotnet/src/Client.cs:1196
  • Protocol v3: The CLI sends permission requests as broadcast permission.requested events, dispatched in CopilotSession._dispatchEvent (nodejs/src/client.ts:1375-1377).

Both v2 adapters are always registered because they are set up before version negotiation; a v3 server simply never invokes them.

3.5 Default Deny When No Handler

If a permission request arrives for a session that has no handler registered (or if the handler call fails), the default is deny with DeniedCouldNotRequestFromUser:

  • Go go/client.go:1513-1517
  • .NET dotnet/src/Session.cs:336-338
  • TypeScript nodejs/src/session.ts:500-504

3.6 requestPermission Flag

All SDKs set requestPermission: true on session create/resume RPC calls, instructing the CLI to route permission decisions through the SDK rather than handling them internally:

  • TypeScript nodejs/src/client.ts:588
  • Python python/copilot/client.py:533
  • Go go/client.go:529

4. Process Security

4.1 CLI Process Spawning

When not using an external server (cliUrl), each SDK spawns the Copilot CLI as a child process:

  • TypeScript Uses spawn() from node:child_processnodejs/src/client.ts:1163-1176
  • Python Uses subprocess.Popen()python/copilot/client.py:1331-1352
  • Go Uses os/exec.CommandContext()go/client.go:1197
  • .NET Uses System.Diagnostics.Processdotnet/src/Client.cs:1067-1068

4.2 Window Hiding on Windows

All four SDKs suppress console window creation on Windows to prevent visual disruption:

SDK Mechanism File:Line
TypeScript windowsHide: true in spawn options nodejs/src/client.ts:1167, 1174
Python subprocess.CREATE_NO_WINDOW creation flag python/copilot/client.py:1325
Go SysProcAttr.HideWindow = true go/process_windows.go:13-14
.NET ProcessStartInfo.CreateNoWindow = true dotnet/src/Client.cs:1047

On non-Windows for Go, configureProcAttr is a no-op (go/process_other.go:9-11).

4.3 Shell Execution Disabled

All SDKs explicitly avoid shell execution:

  • TypeScript spawn() is used directly (no shell: true)
  • Python Arguments are passed as a list to Popen, not as a shell string
  • .NET UseShellExecute = falsedotnet/src/Client.cs:1042

4.4 CLI Arguments

The SDK always passes a fixed set of flags to the CLI process:

--headless --no-auto-update --log-level <level>

Plus transport mode (--stdio or --port <n>), and optionally:

  • --auth-token-env COPILOT_SDK_AUTH_TOKEN (when githubToken is set)
  • --no-auto-login (when useLoggedInUser is false)

These are hardcoded; user-provided cliArgs are prepended before SDK-managed args.

4.5 Process Lifecycle

Graceful stop: SDKs send stop/close signals and wait for process termination with a timeout:

  • Python terminate() then wait(timeout=5) then kill()python/copilot/client.py:385-389
  • TypeScript kill()nodejs/src/client.ts:421
  • Go killProcess() via os.Process.Kill()go/client.go:1282-1289
  • .NET Process.Kill()dotnet/src/Client.cs:355

Force stop: All SDKs provide a forceStop() method that immediately kills the process without waiting:

  • TypeScript SIGKILLnodejs/src/client.ts:497
  • Go osProcess.Kill() outside of start/stop mutex — go/client.go:401-404

4.6 Process Monitoring

Go implements explicit process monitoring with a goroutine (go/client.go:1297-1310) that signals a done channel on exit. The process pointer is stored atomically (go/client.go:95) to allow safe concurrent access for kill operations.

5. Input Validation

5.1 Constructor-Level Validation

All SDKs validate mutually exclusive options at construction time:

  • cliUrl is mutually exclusive with useStdio and cliPath:
    • TypeScript nodejs/src/client.ts:205-207
    • Go go/client.go:140-141
  • isChildProcess must use stdio, not cliUrl:
    • TypeScript nodejs/src/client.ts:209-213
  • Auth options cannot be used with external server: see Section 1.6

5.2 Protocol Version Verification

After connecting, all SDKs verify the CLI server's protocol version via a ping RPC call:

  • TypeScript nodejs/src/client.ts:837-864 — checks MIN_PROTOCOL_VERSION (2) to getSdkProtocolVersion()
  • Python python/copilot/client.py:54MIN_PROTOCOL_VERSION = 2
  • Go go/client.go:1140-1141 — rejects if server version is out of range
  • .NET dotnet/src/Client.cs:974-998

If the version is outside the supported range, the connection is refused with a descriptive error.

5.3 CLI Path Verification

The Node.js SDK verifies the CLI binary exists before attempting to spawn:

// nodejs/src/client.ts:1148-1153
if (!existsSync(this.options.cliPath)) {
    throw new Error(`Copilot CLI not found at ${this.options.cliPath}...`);
}

Python performs a similar check at python/copilot/client.py:1288-1289.

5.4 Port Parsing

For TCP mode, all SDKs parse the port from CLI stdout using regex:

  • TypeScript stdout.match(/listening on port (\d+)/i)nodejs/src/client.ts:1189
  • Python re.search(r"listening on port (\d+)", ...)python/copilot/client.py:1371
  • Go regexp.MustCompile("listening on port (\\d+)")go/client.go:1254
  • .NET ListeningOnPortRegex() generated regex — dotnet/src/Client.cs:1102

5.5 Session Create RPC Payload

Tool definitions are serialized with name, description, and parameters before being sent to the CLI. Parameters go through JSON Schema conversion:

  • TypeScript toJsonSchema() at nodejs/src/client.ts:73-78 — handles both Zod schemas and raw JSON schemas
  • The envValueMode is set to "direct" on all create/resume calls:
    • TypeScript nodejs/src/client.ts:594
    • Python python/copilot/client.py:564
    • Go go/client.go:508

5.6 Permission Request Payload Validation

v2 permission request handlers validate the incoming payload before processing:

  • TypeScript nodejs/src/client.ts:1595-1596 — checks sessionId is string and permissionRequest exists
  • Go go/client.go:1502-1503 — returns error code -32602 if session ID or request is empty
  • Python python/copilot/client.py:1650-1652 — raises ValueError on invalid payload

6. Secret Management

6.1 .gitignore Coverage

The repository uses per-directory .gitignore files. .env files are excluded across multiple SDK directories:

.gitignore File Excludes .env
nodejs/.gitignore:76-80 .env, .env.development.local, .env.test.local, .env.production.local, .env.local
python/.gitignore:123 .env
go/.gitignore:24 .env
Root .gitignore:2 docs/.validation/ (build artifacts only)
dotnet/.gitignore Does not mention .env

6.2 Security-Relevant Environment Variables

The following environment variables carry credentials:

Variable Purpose Where Referenced
COPILOT_SDK_AUTH_TOKEN Internal: token passed to CLI subprocess All four SDK clients
COPILOT_GITHUB_TOKEN GitHub token for Copilot (priority 1 env var) docs/auth/index.md:210
GH_TOKEN GitHub CLI compatible token (priority 2) docs/auth/index.md:211
GITHUB_TOKEN GitHub Actions compatible token (priority 3) docs/auth/index.md:212
GITHUB_COPILOT_API_TOKEN Direct API token docs/auth/index.md:275
COPILOT_API_URL API endpoint for direct API token mode docs/auth/index.md:275
CAPI_HMAC_KEY / COPILOT_HMAC_KEY HMAC signing key docs/auth/index.md:274
GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET OAuth app credentials (app code, not SDK) docs/setup/github-oauth.md:100-101
FOUNDRY_API_KEY Azure AI Foundry API key (BYOK) docs/auth/byok.md:41
OPENAI_API_KEY OpenAI API key (BYOK) docs/auth/byok.md:212
ANTHROPIC_API_KEY Anthropic API key (BYOK) docs/auth/byok.md:291
AZURE_OPENAI_KEY Azure OpenAI API key (BYOK) docs/auth/byok.md:225
COPILOT_CLI_PATH CLI binary path override go/client.go:205

6.3 NODE_DEBUG Suppression

All SDKs remove NODE_DEBUG from the CLI subprocess environment to prevent verbose debug output from polluting stdio transport:

  • TypeScript nodejs/src/client.ts:1135
  • .NET dotnet/src/Client.cs:1059

7. Network Security

7.1 Transport Modes

The SDK communicates with the CLI via two transport modes:

Mode Protocol When Used
stdio (default) JSON-RPC over stdin/stdout pipes Local child process
TCP JSON-RPC over raw TCP socket External server (cliUrl) or port mode

7.2 TCP Connection Details

TCP connections use plain TCP sockets — there is no TLS between SDK and CLI:

  • TypeScript new Socket().connect(port, host)nodejs/src/client.ts:1342-1344
  • Go net.Dialer.DialContext(ctx, "tcp", address) with 10s timeout — go/client.go:1334-1337
  • .NET new TcpClient().ConnectAsync(host, port)dotnet/src/Client.cs:1173-1174
No Built-in Auth on TCP Path

The default host is localhost. The docs note that when using cliUrl in production, the network path between SDK and CLI should be secured (docs/setup/backend-services.md:471): "No built-in auth between SDK and CLI — Secure the network path (same host, VPC, etc.)"

7.3 CLI-to-Cloud Communication

The SDK itself does not make direct API calls to model providers. The CLI subprocess handles all outbound network communication to:

  • GitHub Copilot API
  • Azure AI Foundry / Azure OpenAI endpoints
  • OpenAI API
  • Anthropic API
  • Local model servers (Ollama, Foundry Local)

BYOK provider baseUrl values are passed through the session config to the CLI, which makes the actual HTTP(S) requests.

7.4 URL Parsing

The cliUrl parameter is parsed to extract host and port. The Node.js SDK has a parseCliUrl method (nodejs/src/client.ts:224). The Go SDK has a parseCliUrl function (go/client.go:151). The Python SDK's test suite confirms HTTPS URLs are accepted (python/test_client.py:58-59).

7.5 Proxy Support

There is no explicit proxy configuration in the SDK layer. Proxy handling, if any, would be in the CLI subprocess, which inherits the parent process's environment variables (including standard proxy env vars like HTTP_PROXY, HTTPS_PROXY).

8. Attack Surface

8.1 Entry Points

Entry Point Description Risk Context
SDK Constructor Accepts cliPath, cliUrl, githubToken, env vars cliPath is used directly as executable path
Session Create Accepts model name, provider config (with API keys), tools, system message, working directory Tool definitions and system messages are passed to CLI
Message Send User prompts sent to CLI Prompt content goes to model provider
Tool Handler Callbacks SDK-registered tools invoked by CLI Tool arguments come from model output
Permission Handler SDK-registered handler invoked by CLI Must decide whether to allow actions
TCP Listener When CLI runs in headless mode on a port Network-accessible JSON-RPC endpoint

8.2 Tool Registration and Execution

Custom tools are registered at session creation time. The tool handler receives arguments from the CLI, which come from model output:

// nodejs/src/types.ts:132-142
export interface ToolInvocation {
    sessionId: string;
    toolCallId: string;
    toolName: string;
    arguments: unknown;  // From model output
}

The arguments field is typed as unknown — the SDK does not validate tool arguments against the declared schema. Schema validation (if any) occurs in the CLI or model provider side.

8.3 Tool Override Mechanism

Tools can be marked with overridesBuiltInTool: true (nodejs/src/types.ts:169), which allows SDK-registered tools to replace CLI built-in tools. Without this flag, a name clash results in an error.

8.4 System Message Injection Surface

Session creation accepts a systemMessage parameter (nodejs/src/client.ts:584) that is sent to the CLI. The SystemMessageAppendConfig type (nodejs/src/types.ts:202-208) supports an "append" mode with a content string. This content is concatenated into the system prompt.

8.5 Working Directory

Session creation accepts a workingDirectory parameter (nodejs/src/client.ts:591) that controls where the CLI operates. This path is not validated by the SDK before being sent to the CLI.

8.6 MCP Server Configuration

Session creation accepts an mcpServers parameter (nodejs/src/client.ts:593) for Model Context Protocol server definitions, which the CLI connects to as additional tool sources.

8.7 Custom Agent Configuration

Session creation accepts customAgents and agent parameters (nodejs/src/client.ts:595-596) that configure agent behavior. The agent config can include MCP server references (python/copilot/client.py:1270).

8.8 Headless TCP Mode Exposure

When the CLI runs in headless mode (--headless --port <n>), it exposes a JSON-RPC server on a TCP port with no built-in authentication between SDK and CLI. The docs explicitly note this: docs/setup/backend-services.md:471.

8.9 cliArgs Passthrough

All SDKs accept user-provided cliArgs that are prepended to SDK-managed arguments:

  • TypeScript nodejs/src/client.ts:1111...this.options.cliArgs
  • Python python/copilot/client.py:1292-1293
  • Go go/client.go:1164
  • .NET dotnet/src/Client.cs:1007-1009

These args are not sanitized by the SDK before being passed to the process.

9. BYOK (Bring Your Own Key)

9.1 Overview

BYOK mode allows using the SDK without a GitHub Copilot subscription by providing API keys from third-party model providers. Documented in docs/auth/byok.md.

9.2 Supported Providers

Provider type Value Authentication
OpenAI "openai" apiKey or bearerToken
Azure OpenAI / Azure AI Foundry "azure" apiKey
Anthropic "anthropic" apiKey
Ollama (local) "openai" None required
Microsoft Foundry Local "openai" None required

Reference: docs/auth/byok.md:7-14

9.3 Provider Config Fields

From docs/auth/byok.md:172-181:

Field Type Description
type "openai" / "azure" / "anthropic" Provider type
baseUrl string Required. API endpoint URL
apiKey string API key (optional for local providers)
bearerToken string Bearer token auth (takes precedence over apiKey)
wireApi "completions" / "responses" API format
azure.apiVersion string Azure API version

9.4 Bearer Token Limitations

Bearer tokens are static only (docs/auth/byok.md:307): "The bearerToken option accepts a static token string only. The SDK does not refresh this token automatically."

9.5 Identity Provider Limitations

BYOK does not support (docs/auth/byok.md:426-430):

  • Microsoft Entra ID (Azure AD) managed identities or service principals
  • Third-party OIDC, SAML, or federated identity
  • Azure Managed Identity natively

9.6 Azure Managed Identity Workaround

docs/setup/azure-managed-identity.md documents a pattern where DefaultAzureCredential from the Azure Identity library obtains a short-lived bearer token, which is then passed as bearer_token in the BYOK provider config. The application is responsible for token refresh before expiry (~1 hour).

9.7 API Key Transmission to CLI

BYOK API keys and bearer tokens are passed in the session create RPC payload as part of the provider configuration. In Python, bearer_token is mapped to bearerToken for wire format:

# python/copilot/client.py:1239-1240
if "bearer_token" in provider:
    wire_provider["bearerToken"] = provider["bearer_token"]

The keys travel over the JSON-RPC connection (stdio pipes or TCP socket) to the CLI, which then uses them for outbound API calls.

9.8 Custom Model Listing

BYOK supports onListModels override (docs/auth/byok.md:311-417), which completely replaces the CLI's models.list RPC. Results are cached after first call.

10. Security Policies

10.1 SECURITY.md

The repository's SECURITY.md (root level) establishes:

  • Disclosure policy: Coordinated disclosure via email to opensource-security@github.com (SECURITY.md:15)
  • No public disclosure: Vulnerabilities must not be reported via GitHub issues, discussions, or pull requests (SECURITY.md:13)
  • Bug bounty scope: Open source repositories are outside GitHub's bug bounty scope (SECURITY.md:7)
  • Safe harbor: References GitHub's Safe Harbor Policy (SECURITY.md:31)

10.2 Required Disclosure Information

From SECURITY.md:17-25, reporters are asked to provide:

  • Type of issue (buffer overflow, SQL injection, XSS, etc.)
  • Full paths of affected source files
  • Location of affected code (tag/branch/commit or URL)
  • Special configuration to reproduce
  • Step-by-step reproduction instructions
  • Proof-of-concept or exploit code
  • Impact assessment

The source code carries Microsoft copyright headers:

  • TypeScript nodejs/src/client.ts:1-3 — "Copyright (c) Microsoft Corporation. All rights reserved."
  • .NET dotnet/src/Client.cs:1-3 — same

10.4 Protocol Version as Security Boundary

The protocol version negotiation (MIN_PROTOCOL_VERSION = 2) acts as a compatibility gate. A mismatched server is rejected before any session operations occur. This prevents the SDK from communicating with potentially incompatible or outdated CLI servers that may have different security behaviors.

Summary of Security-Relevant Architecture

Security Boundary Overview
flowchart LR
  A["<b>Application</b><br/>Provides token<br/>Registers tools<br/>Handles permissions<br/>Sends prompts"] --> B["<b>SDK Client</b><br/>(in-process)<br/>Validates opts<br/>Spawns CLI<br/>JSON-RPC conn<br/>Routes events<br/>Env var token"]
  B --> C["<b>Copilot CLI</b><br/>(subprocess / TCP)<br/>Auth to GitHub<br/>BYOK to APIs<br/>Tool execution<br/>Model calls"]
  C --> D["<b>Cloud Services</b><br/>GitHub API<br/>OpenAI<br/>Azure AI<br/>Anthropic"]
          

Key security boundaries:

  1. Application <-> SDK: In-process trust boundary; SDK validates constructor options and requires permission handlers.
  2. SDK <-> CLI: Process boundary; tokens passed via env vars, communication over JSON-RPC (stdio or TCP). No TLS on TCP path.
  3. CLI <-> Cloud: Network boundary; the CLI handles all outbound HTTPS to model providers and GitHub APIs.