Skip to content

Commit 218a001

Browse files
authored
fix: route Copilot /models to COPILOT_API_TARGET, not GitHub REST API (#1952)
* Initial plan * fix: route Copilot /models to COPILOT_API_TARGET, not GitHub REST API Agent-Logs-Url: https://github.com/github/gh-aw-firewall/sessions/3b2257ec-f9b7-467f-8d89-c87a516dc530 --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
1 parent 0c5eca0 commit 218a001

2 files changed

Lines changed: 28 additions & 0 deletions

File tree

containers/api-proxy/server.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -888,6 +888,31 @@ if (require.main === module) {
888888
const contentLength = parseInt(req.headers['content-length'], 10) || 0;
889889
if (checkRateLimit(req, res, 'copilot', contentLength)) return;
890890

891+
// Copilot CLI 1.0.21+ calls GET /models at startup (to list or validate models).
892+
// The /models endpoint lives on the Copilot inference API (COPILOT_API_TARGET),
893+
// NOT on the GitHub REST API. Explicitly use COPILOT_GITHUB_TOKEN for this
894+
// request so the GitHub OAuth token is used even when both COPILOT_GITHUB_TOKEN
895+
// and COPILOT_API_KEY are configured (COPILOT_API_KEY alone is not accepted by
896+
// the /models endpoint).
897+
let reqPathname;
898+
try {
899+
reqPathname = new URL(req.url, 'http://localhost').pathname;
900+
} catch {
901+
logRequest('warn', 'copilot_proxy_malformed_url', {
902+
message: 'Malformed request URL in Copilot proxy — rejecting with 400',
903+
});
904+
res.writeHead(400, { 'Content-Type': 'application/json' });
905+
res.end(JSON.stringify({ error: 'Invalid request URL' }));
906+
return;
907+
}
908+
const isModelsPath = reqPathname === '/models' || reqPathname.startsWith('/models/');
909+
if (isModelsPath && req.method === 'GET' && COPILOT_GITHUB_TOKEN) {
910+
proxyRequest(req, res, COPILOT_API_TARGET, {
911+
'Authorization': `Bearer ${COPILOT_GITHUB_TOKEN}`,
912+
}, 'copilot');
913+
return;
914+
}
915+
891916
proxyRequest(req, res, COPILOT_API_TARGET, {
892917
'Authorization': `Bearer ${COPILOT_AUTH_TOKEN}`,
893918
}, 'copilot');

src/docker-manager.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1535,6 +1535,9 @@ export function generateDockerCompose(
15351535
...(config.geminiApiBasePath && { GEMINI_API_BASE_PATH: config.geminiApiBasePath }),
15361536
// Forward GITHUB_SERVER_URL so api-proxy can auto-derive enterprise endpoints
15371537
...(process.env.GITHUB_SERVER_URL && { GITHUB_SERVER_URL: process.env.GITHUB_SERVER_URL }),
1538+
// Forward GITHUB_API_URL so api-proxy can use the correct GitHub REST API hostname
1539+
// on GHES/GHEC (e.g. https://ghes.example.com/api/v3 or api.mycompany.ghe.com)
1540+
...(process.env.GITHUB_API_URL && { GITHUB_API_URL: process.env.GITHUB_API_URL }),
15381541
// Route through Squid to respect domain whitelisting
15391542
HTTP_PROXY: `http://${networkConfig.squidIp}:${SQUID_PORT}`,
15401543
HTTPS_PROXY: `http://${networkConfig.squidIp}:${SQUID_PORT}`,

0 commit comments

Comments
 (0)