← Back to PRs

#22352: fix(auth): validate Copilot token cache belongs to requesting account

by xinhuagu open 2026-02-21 02:20 View on GitHub →
size: S trusted-contributor
## Problem `resolveCopilotApiToken()` uses a single shared cache file (`github-copilot.token.json`) for all Copilot auth profiles. When multiple GitHub accounts are configured, a cached API token from account A is returned for requests meant for account B. If account A is rate-limited, account B's requests fail too — even though account B has available quota (#22264). The cache check only validates expiry (`isTokenUsable`), never whether the cached token actually belongs to the requesting account. ## Fix Store a SHA-256 hash of the `ghu_` token alongside the cached API token. On cache read, compare the hash against the current request's `githubToken`. A mismatch triggers a fresh token exchange instead of returning the wrong account's token. This is backward-compatible: existing cache files without `githubTokenHash` simply miss the cache on first read and get refreshed with the hash included. ## Changes - `src/providers/github-copilot-token.ts`: Add `githubTokenHash` to `CachedCopilotToken`, validate on read, persist on write - `src/providers/github-copilot-token.test.ts`: Add test for cross-account cache rejection, update existing cache test to include hash Closes #22264 <!-- greptile_comment --> <h3>Greptile Summary</h3> Fixes a multi-account Copilot auth bug where a single shared cache file (`github-copilot.token.json`) could serve a stale token from account A to requests intended for account B, causing cross-account rate-limit bleed (#22264). - Adds a SHA-256 hash of the `ghu_` GitHub token to the cached payload (`githubTokenHash` field in `CachedCopilotToken`) - On cache read, validates the hash matches the requesting account's token before returning a cached result; a mismatch triggers a fresh token exchange - Backward-compatible: existing cache files without `githubTokenHash` simply miss on first read and get refreshed with the hash included - Adds three well-scoped test cases covering cache hit (hash match), cache miss (hash mismatch / cross-account), and backward compatibility (missing hash field) <h3>Confidence Score: 5/5</h3> - This PR is safe to merge — it's a targeted, backward-compatible bug fix with good test coverage. - The change is minimal and well-scoped: a single additional field on the cache type, one hash comparison added to the cache check, and one hash write on cache save. The backward-compat path (missing hash causes cache miss) is correct by construction since `undefined !== string`. The SHA-256 hashing avoids storing raw tokens. All three callers in the codebase pass `githubToken` to the function already, so no caller changes are needed. Tests cover the key scenarios. - No files require special attention <sub>Last reviewed commit: d1d2a37</sub> <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs