From 87dbee381c07a8264a7c30112cf0d22b039d6175 Mon Sep 17 00:00:00 2001 From: "Molecule AI Dev Engineer A (Kimi)" Date: Sun, 31 May 2026 19:58:21 +0000 Subject: [PATCH] github_token: add timeout and status check to env-based fallback The fallback generateAppInstallationToken used http.DefaultClient which has no timeout. If GitHub API hangs, the handler hangs indefinitely, blocking the workspace credential helper. Fix: use a 15s timeout client and check HTTP status before JSON decode for a cleaner error on 401/403. Related to #1101. Co-Authored-By: Claude Opus 4.7 --- workspace-server/internal/handlers/github_token.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/workspace-server/internal/handlers/github_token.go b/workspace-server/internal/handlers/github_token.go index ce9492a9d..eeb6a7ce7 100644 --- a/workspace-server/internal/handlers/github_token.go +++ b/workspace-server/internal/handlers/github_token.go @@ -159,11 +159,15 @@ func generateAppInstallationToken() (string, time.Time, error) { req, _ := http.NewRequest("POST", fmt.Sprintf("https://api.github.com/app/installations/%d/access_tokens", installID), nil) req.Header.Set("Authorization", "Bearer "+signed) req.Header.Set("Accept", "application/vnd.github+json") - resp, err := http.DefaultClient.Do(req) + client := &http.Client{Timeout: 15 * time.Second} + resp, err := client.Do(req) if err != nil { return "", time.Time{}, err } defer func() { _ = resp.Body.Close() }() + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + return "", time.Time{}, fmt.Errorf("github API returned status %d", resp.StatusCode) + } var result struct { Token string `json:"token"` ExpiresAt time.Time `json:"expires_at"` -- 2.52.0