fix: always derive GH_HOST from GITHUB_SERVER_URL to prevent proxy leakage#1493
fix: always derive GH_HOST from GITHUB_SERVER_URL to prevent proxy leakage#1493
Conversation
…akage When --env-all passes through a proxy-rewritten GH_HOST (e.g. localhost:18443 from DIFC proxy), gh CLI fails with "none of the git remotes correspond to GH_HOST". Fix by always deriving GH_HOST from GITHUB_SERVER_URL (the canonical source injected by the Actions runner) instead of preserving leaked proxy values. For GHES/GHEC: overrides any leaked value with the correct hostname. For github.com: deletes any leaked GH_HOST so gh CLI uses its default. Closes #1492 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
✅ Coverage Check PassedOverall Coverage
📁 Per-file Coverage Changes (1 files)
Coverage comparison generated by |
There was a problem hiding this comment.
Pull request overview
This PR prevents proxy-leaked GH_HOST values (passed through via --env-all) from breaking gh CLI operations inside the agent container by ensuring GH_HOST is derived from the canonical GITHUB_SERVER_URL.
Changes:
- Always set
GH_HOSTfromGITHUB_SERVER_URLwhen targeting GHES/GHEC; otherwise remove any leakedGH_HOST(github.com/unset cases). - Update and extend tests to assert proxy-rewritten
GH_HOSTis overridden/removed as appropriate.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/docker-manager.ts | Force GH_HOST to be derived from GITHUB_SERVER_URL, and delete leaked values on github.com/unset paths. |
| src/docker-manager.test.ts | Updates existing test expectation and adds a github.com case to ensure leaked GH_HOST is removed. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
src/docker-manager.ts
Outdated
| // GITHUB_SERVER_URL is injected by the Actions runner and always points to the real | ||
| // GitHub instance, so it is the canonical source of truth. |
There was a problem hiding this comment.
The comment says GITHUB_SERVER_URL “always points to the real GitHub instance”, but this function is also used outside GitHub Actions where GITHUB_SERVER_URL can be unset (and the code below explicitly handles that). Consider rewording to clarify this guarantee only applies when the Actions runner injects GITHUB_SERVER_URL (i.e. in GitHub Actions).
| // GITHUB_SERVER_URL is injected by the Actions runner and always points to the real | |
| // GitHub instance, so it is the canonical source of truth. | |
| // When running inside GitHub Actions, GITHUB_SERVER_URL is injected by the Actions | |
| // runner and points to the real GitHub instance for the workflow run, so within that | |
| // context it is the canonical source of truth. Outside Actions it may be unset. |
src/docker-manager.ts
Outdated
| // On github.com (or when GITHUB_SERVER_URL is unset), GH_HOST should not be set. | ||
| // If --env-all passed through a proxy-rewritten value, remove it so gh CLI | ||
| // uses its default (github.com). See: gh-aw-firewall#1492 | ||
| delete environment.GH_HOST; | ||
| logger.debug('Removed proxy-rewritten GH_HOST (GITHUB_SERVER_URL targets github.com)'); |
There was a problem hiding this comment.
The debug message “Removed proxy-rewritten GH_HOST (GITHUB_SERVER_URL targets github.com)” can be misleading because this branch also runs when GITHUB_SERVER_URL is unset/empty/invalid (since extractGhHostFromServerUrl returns null in those cases). Consider adjusting the log message (and/or condition) so it accurately reflects why GH_HOST was removed.
| // On github.com (or when GITHUB_SERVER_URL is unset), GH_HOST should not be set. | |
| // If --env-all passed through a proxy-rewritten value, remove it so gh CLI | |
| // uses its default (github.com). See: gh-aw-firewall#1492 | |
| delete environment.GH_HOST; | |
| logger.debug('Removed proxy-rewritten GH_HOST (GITHUB_SERVER_URL targets github.com)'); | |
| // When GITHUB_SERVER_URL does not yield a custom host (e.g. github.com, unset, or invalid), | |
| // GH_HOST should not be set. If --env-all passed through a proxy-rewritten value, remove it | |
| // so gh CLI uses its default behavior (github.com). See: gh-aw-firewall#1492 | |
| delete environment.GH_HOST; | |
| logger.debug('Removed GH_HOST from environment; falling back to gh CLI default since GITHUB_SERVER_URL did not yield a custom host override'); |
Smoke Test Results — Copilot Engine
Overall: PASS Author:
|
|
Smoke Test Results — PASS ✅ GitHub MCP: #1486 feat(api-proxy): add WebSocket upgrade support to fix Codex /v1/responses streaming; #1404 chore(deps): bump the all-github-actions group with 21 updates
|
Chroot Version Comparison Results
Result: FAILED — Python and Node.js versions differ between host and chroot environments. This is expected behavior: chroot uses the system-installed versions from the Ubuntu base image, while the host runner has newer tool-cache versions.
|
This comment has been minimized.
This comment has been minimized.
…violation in Codex workflows (#1494) * Initial plan * fix: replace xpia.md with safe inline policy to fix cyber_policy_violation * fix: address code review feedback on xpia.md replacement logic Agent-Logs-Url: https://github.com/github/gh-aw-firewall/sessions/ecbda070-c667-4859-8ca2-8b15dee1e0a2 --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
|
Smoke test results (run 23713266323) ✅ GitHub MCP — #1494: fix: replace xpia.md with safe inline policy | #1486: feat(api-proxy): add WebSocket upgrade support Overall: PASS
|
This comment has been minimized.
This comment has been minimized.
Smoke Test Results — Copilot Engine
Overall: PASS PR author:
|
Chroot Version Comparison Results
Overall: Not all tests passed. Python and Node.js versions differ between host and chroot.
|
Replace cybersecurity-triggering content (was using <security> tag, 'network access controls', 'circumventing', 'authentication tokens', 'sandboxed environment') with neutral operational policy language using a <policy> tag. These terms triggered OpenAI's cyber_policy_violation filter, causing Smoke Codex to fail with 'temporarily limited for potentially suspicious activity related to cybersecurity'. Also add xpiaSafeBlockRegex so the postprocess script is idempotent when SAFE_XPIA_CONTENT changes (can update already-replaced blocks without requiring a full recompile from .md source). Regenerated smoke-codex.lock.yml and secret-digger-codex.lock.yml. Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
|
Smoke Test Results — PASS
|
Smoke Test Results✅ GitHub MCP: Last 2 merged PRs retrieved
✅ Playwright: https://github.com title contains "GitHub" Overall: PASS | PR by
|
Chroot Version Comparison Results
Result: FAILED — Python and Node.js versions differ between host and chroot environments.
|
This comment has been minimized.
This comment has been minimized.
|
@copilot create a fix for this comment #1493 (comment) |
Fixed in a4dffe1. Both the comment and the debug log message have been updated:
|
This comment has been minimized.
This comment has been minimized.
Run npm audit fix to resolve: - handlebars 4.0.0-4.7.8: critical (JS injection, prototype pollution) - brace-expansion 4.0.0-5.0.4: moderate (DoS via zero-step sequence) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Smoke Test Results
Overall: PASS
|
This comment has been minimized.
This comment has been minimized.
|
🤖 Smoke test results for ✅ GitHub MCP — Last 2 merged PRs: #1495 "fix: use neutral policy language in SAFE_XPIA_CONTENT..." · #1494 "fix: replace xpia.md with safe inline policy..." Overall: PASS
|
Chroot Version Comparison Results
Result: ❌ Not all tests passed — Python and Node.js versions differ between host and chroot environments.
|
Remove existsSync guard before readFileSync to eliminate TOCTOU race condition (js/file-system-race). Use try/catch on readFileSync instead, which atomically handles missing files. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Smoke Test Results — Copilot ✅ PASS
PR author: Overall: PASS
|
|
Smoke Test Results — PASS
|
Chroot Version Comparison Results
Result: Not all tests passed. Python and Node.js versions differ between host and chroot environments. Go versions match.
|
🏗️ Build Test Suite Results
Overall: 8/8 ecosystems passed — ✅ PASS
|
Problem
When
--env-allpasses through a proxy-rewrittenGH_HOST(e.g.localhost:18443from a DIFC proxy), theghCLI inside the container fails:The old code had a
!environment.GH_HOSTguard that preserved whatever value--env-allpassed through, even if it was a proxy artifact.Fix
Always derive
GH_HOSTfromGITHUB_SERVER_URL(the canonical source injected by the Actions runner), overriding any proxy-leaked values:GH_HOSTto the correct hostname derived fromGITHUB_SERVER_URLGH_HOSTsoghCLI uses its defaultGITHUB_SERVER_URLis set by the runner itself and always points to the real GitHub instance — it is never rewritten by proxies.Tests
GH_HOSTis overridden (not preserved)GH_HOSTis removed on github.comReferences