fix: exclude GITHUB_TOKEN from agent container when API proxy is enabled - #6250
Conversation
GITHUB_TOKEN and GH_TOKEN were in the alwaysForwardVars list in env-passthrough.ts, bypassing the credential isolation exclusion set. This meant the real GitHub token was always forwarded to the agent container even when enableApiProxy was true (which is always, since strict security mode forces it on). Two fixes: 1. alwaysForwardVars loop now checks the excludedEnvVars set, so excluded vars are no longer unconditionally forwarded 2. GITHUB_TOKEN and GH_TOKEN are added to the enableApiProxy exclusion block (previously only excluded when difcProxyHost was set) This matches the existing behavior for COPILOT_GITHUB_TOKEN, OPENAI_API_KEY, and ANTHROPIC_API_KEY which were already correctly excluded from the agent environment. Fixes failing integration tests: one-shot-tokens.test.ts (8 failures) and token-unset.test.ts (5 failures) on main. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8dcc99fc-3d0e-40c5-8b75-bc43d9bf5dee
✅ Coverage Check PassedOverall Coverage
📁 Per-file Coverage Changes (1 files)
Coverage comparison generated by |
There was a problem hiding this comment.
Pull request overview
Prevents GitHub credentials from being forwarded into the agent container when API proxy isolation is active.
Changes:
- Adds
GITHUB_TOKENandGH_TOKENto API-proxy exclusions. - Applies exclusions to always-forwarded variables.
- Expands exclusion-set tests.
Show a summary per file
| File | Description |
|---|---|
excluded-vars.ts |
Excludes GitHub tokens in API-proxy mode. |
excluded-vars.test.ts |
Tests GitHub token exclusions. |
env-passthrough.ts |
Honors exclusions during default forwarding. |
Review details
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 3/3 changed files
- Comments generated: 4
- Review effort level: Medium
| excludedEnvVars.add('GITHUB_TOKEN'); | ||
| excludedEnvVars.add('GH_TOKEN'); |
| // GitHub tokens are also excluded when API proxy is enabled (strict mode). | ||
| // When a DIFC proxy is present, gh CLI uses the proxy wrapper; otherwise | ||
| // the one-shot token library provides defense-in-depth by clearing | ||
| // /proc/self/environ after first read. |
|
|
||
| for (const v of alwaysForwardVars) { | ||
| if (process.env[v]) { | ||
| if (process.env[v] && !excludedEnvVars.has(v)) { |
|
⏳ Copilot review left inline comments. @lpcox To proceed:
|
|
@copilot Fix the code for all comments in this review thread. When a review comment includes a suggested change, apply the suggestion exactly. Do not make changes beyond what is described in the linked review thread. |
|
Chroot tests passed! Smoke Chroot - All security and functionality tests succeeded. |
|
✨ The prophecy is fulfilled... Smoke Codex has completed its mystical journey. The stars align. 🌟 |
|
✅ Contribution Check completed successfully! |
|
❌ Smoke Copilot BYOK AOAI (api-key) reports failed. AOAI BYOK (api-key) mode investigation needed... |
|
🔑 Smoke Copilot PAT PAT auth validated. All systems operational. ✅ |
|
✅ Build Test Suite completed successfully! |
|
🔌 Smoke Services — All services reachable! ✅ |
|
📰 VERDICT: Smoke Docker Sbx has concluded. All systems operational. This is a developing story. 🎤 |
|
✅ Smoke Claude passed |
|
📡 Smoke OTel Tracing completed. All tracing scenarios validated. ✅ |
|
🚀 Security Guard has started processing this pull request |
|
✅ Smoke Copilot BYOK completed. Copilot BYOK mode operational. 🔓 |
|
📰 VERDICT: Smoke Copilot has concluded. All systems operational. This is a developing story. 🎤 |
|
🦎🟣 Smoke gVisor Claude completed. gVisor + Claude smoke test passed. ✅ |
|
🦎 Smoke gVisor completed. gVisor smoke test passed. ✅ |
|
❌ Smoke Copilot BYOK AOAI (Entra) reports failed. AOAI BYOK (Entra) mode investigation needed... |
|
🦎🏗️ Smoke gVisor Build Test completed. gVisor build test passed. ✅ |
|
✅ Smoke Gemini completed. All facets verified. 💎 Smoke test starting |
|
🐳🔮 Smoke Docker Sbx Codex completed. Docker sbx + Codex smoke test passed. ✅ |
|
🦎🔮 Smoke gVisor Codex completed. gVisor + Codex smoke test passed. ✅ |
|
🐳🏗️ Smoke Docker Sbx Build Test completed. Docker sbx build test passed. ✅ |
|
Thanks for the focused security fix. The implementation, tests, documentation update, and file organization align with the CONTRIBUTING.md guidance. One PR requirement is still missing: please reference the related GitHub issue(s), or state explicitly that there is no related issue, under the Pull Request Process / pull request requirements section (CONTRIBUTING.md, lines 109-113). Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "awmgmcpg"See Network Configuration for more information.
|
Smoke Test: Claude Engine Validation
Overall result: PASS Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "awmgmcpg"See Network Configuration for more information.
|
Smoke Test: Services Connectivity
Overall: FAIL — Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "awmgmcpg"See Network Configuration for more information.
|
Smoke Test: Copilot PAT Auth — INCONCLUSIVE
Auth mode: PAT (COPILOT_GITHUB_TOKEN) Pre-computed outputs were not injected into prompt. MCP reads confirmed functional. Overall: INCONCLUSIVE (workflow template expansion issue) Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "awmgmcpg"See Network Configuration for more information.
|
🔍 Smoke Test: API Proxy OpenTelemetry Tracing
Overall: ✅ All 5 scenarios pass. OTEL tracing integration is fully operational. Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "awmgmcpg"See Network Configuration for more information.
|
Smoke Test: Copilot BYOK (Direct Mode) — PASS
Running in direct BYOK mode ( Overall: PASS Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "awmgmcpg"See Network Configuration for more information.
|
|
🦎🟣 gVisor + Claude runtime: unconfirmed (
Overall: PASS (core firewall + connectivity tests passed; runtime marker not present in /proc/version) Warning Firewall blocked 2 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "example.com"
- "host.docker.internal"See Network Configuration for more information.
|
Smoke Test Results
Overall status: FAIL Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "localhost"See Network Configuration for more information.
|
🦎 gVisor Smoke Test Results
Overall: PASS | @lpcox Warning Firewall blocked 2 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "example.com"
- "host.docker.internal"See Network Configuration for more information.
|
|
🦎🔮 gVisor + Codex runtime: confirmed Warning Firewall blocked 2 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "172.30.0.1"
- "example.com"See Network Configuration for more information.
|
🔬 Smoke Test Results
Overall: PASS Author: @lpcox Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "awmgmcpg"See Network Configuration for more information.
|
🦎🏗️ gVisor Build Test Results
Overall: FAIL Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "host.docker.internal"See Network Configuration for more information.
|
Chroot Version Comparison
Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "awmgmcpg"See Network Configuration for more information.
|
🔬 Smoke Test Results — Docker Sbx
Overall:
|
🏗️ Build Test Suite Results
Overall: 8/8 ecosystems passed — ✅ PASS Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "awmgmcpg"See Network Configuration for more information.
|
|
🐳🔮 Docker sbx + Codex
|
🐳🟣 Docker sbx + Claude — Smoke Test
Overall: FAIL — off-allowlist domains are not being blocked.
|
🐳🏗️ Docker Sbx Build Test Results
Overall: FAIL
|
Smoke Test\n- fix: update CI workflow tests for new compiler action path format\n- chore: upgrade gh-aw extension to latest pre-release\n- GitHub PR review: ✅\n- Playwright: ✅\n- File write: ✅\n- Build: ❌\n- Overall: FAILWarning Firewall blocked 2 domainsThe following domains were blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "awmgmcpg"
- "registry.npmjs.org"See Network Configuration for more information.
|
Summary
Security fix:
GITHUB_TOKENandGH_TOKENwere leaked to the agent container, bypassing credential isolation.Root Cause
In
env-passthrough.ts,GITHUB_TOKENandGH_TOKENwere in thealwaysForwardVarslist, which unconditionally forwarded them to the agent container without checking the exclusion set. SinceapplySecurityMode()forcesenableApiProxy = truein both strict and legacy modes, the credential isolation exclusion set should prevent these tokens from reaching the agent — butalwaysForwardVarsbypassed that check entirely.Other credentials (
COPILOT_GITHUB_TOKEN,OPENAI_API_KEY,ANTHROPIC_API_KEY) were correctly isolated because they were in a conditional block gated on!config.enableApiProxy(which is alwaysfalse).Fix
env-passthrough.ts: ThealwaysForwardVarsloop now checksexcludedEnvVars.has(v)before forwarding, so excluded vars are no longer unconditionally forwarded.excluded-vars.ts:GITHUB_TOKENandGH_TOKENare now added to theenableApiProxyexclusion block (previously only excluded whendifcProxyHostwas set).Impact
GITHUB_TOKENandGH_TOKENare no longer exposed in the agent container's environment when the API proxy is enabled (always, in current builds)ghCLI uses the CLI proxy wrapper (no direct token needed)Testing
main:one-shot-tokens.test.ts(8 failures)token-unset.test.ts(5 failures)excluded-vars.test.tswith new test cases for theenableApiProxy→GITHUB_TOKEN/GH_TOKENexclusion