You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Local sandbox 'Authenticate gh' silently uses an unrelated cached fine-grained PAT instead of active gh OAuth session, with no visibility into which credential is chosen #4804
With local sandboxing enabled (/sandbox enable) and the "Authenticate gh" auth setting on (default), the GH_TOKEN exported into the sandboxed environment did not correspond to my active gh session.
gh auth status (run on the host, outside the sandbox) showed I was logged in via the OAuth device flow, with a gho_... token and scopes admin:public_key, gist, read:org, repo — i.e. full private repo access.
Inside a Copilot CLI sandboxed session, echo $GH_TOKEN / gh repo list <org> --visibility private showed access to only one private repository in my org, via a token in the fine-grained PAT format (github_pat_...).
After investigating, I found the actual token being used: an old fine-grained PAT I had created previously and scoped intentionally to a single, unrelated repository (not the repo I was actively working in).
This PAT is neither the active gh auth status OAuth session (keyring-stored gho_ token) nor the GitHub App ghu_ token found in ~/.config/github-copilot/auth.db.
I was unable to determine, from inside a Copilot CLI session or from documentation, why this specific cached PAT was selected over my active OAuth login, or where exactly it was being read from/cached. The lack of visibility made this very difficult to diagnose — I only found the answer by manually checking GitHub's "Active tokens" org admin page and recognizing a token I had created weeks earlier for unrelated purposes.
Expected behavior
When "Authenticate gh" is enabled for the local sandbox, I would expect one of the following:
The sandbox's GH_TOKEN to be derived from the currently active gh auth status account/session (respecting gh auth switch), not from some other cached credential, OR
If Copilot CLI intentionally uses a different/cached credential for the sandbox (e.g. a previously-supplied GH_TOKEN/GITHUB_TOKEN env var), this should be clearly surfaced to the user — e.g. via /sandbox or /env, showing which token/account is being exported into the sandbox and why, without requiring the user to manually diff PAT prefixes and check GitHub's org "Active tokens" page.
Reproduction steps
Log in normally via gh auth login (OAuth device flow), confirm with gh auth status that the active session has broad repo scope.
Separately, at some earlier point, create (or have previously created) a fine-grained PAT scoped to only one specific repository, for an unrelated purpose.
Launch copilot, enable local sandboxing (/experimental on if needed, then /sandbox enable), leave "Authenticate gh" at its default (on).
Inside the Copilot CLI session, ask the agent to run gh repo list <org> --visibility private or inspect $GH_TOKEN.
Observe that the token exported into the sandbox matches the old, narrowly-scoped fine-grained PAT from step 2 — not the active OAuth session from step 1 — with no indication in the CLI of which credential was selected or why.
Additional context
/env and /sandbox do not currently surface which specific token/account was selected for GH_TOKEN in the sandbox, making this essentially undiagnosable without manual, external investigation (comparing token prefixes, checking org "Active tokens" pages, etc.).
Docs reference (Configuring local sandbox settings → Auth tab): "Authenticate gh: Export GH_TOKEN so that GitHub CLI ... works inside the sandbox without reaching its stored credentials (configuration directory or OS keychain), which the sandbox blocks." This explains that a substitute token is exported, but not how that substitute is selected when multiple credentials (OAuth session, GitHub App ghu_ token, cached fine-grained PATs) exist on the host.
Add a way to inspect, from within a session (e.g. /sandbox Auth tab or /env), exactly which token/account is currently selected for sandboxed gh/git operations, including its origin (active gh auth status session vs. a manually-set GH_TOKEN/GITHUB_TOKEN env var vs. some other cached credential) and its repository scope.
Consider making the sandboxed GH_TOKEN follow the currently active gh auth status account by default, rather than silently preferring a possibly-stale GH_TOKEN/GITHUB_TOKEN env var or other cached credential.
Describe the bug
With local sandboxing enabled (
/sandbox enable) and the "Authenticate gh" auth setting on (default), theGH_TOKENexported into the sandboxed environment did not correspond to my activeghsession.gh auth status(run on the host, outside the sandbox) showed I was logged in via the OAuth device flow, with agho_...token and scopesadmin:public_key,gist,read:org,repo— i.e. full private repo access.echo $GH_TOKEN/gh repo list <org> --visibility privateshowed access to only one private repository in my org, via a token in the fine-grained PAT format (github_pat_...).gh auth statusOAuth session (keyring-storedgho_token) nor the GitHub Appghu_token found in~/.config/github-copilot/auth.db.I was unable to determine, from inside a Copilot CLI session or from documentation, why this specific cached PAT was selected over my active OAuth login, or where exactly it was being read from/cached. The lack of visibility made this very difficult to diagnose — I only found the answer by manually checking GitHub's "Active tokens" org admin page and recognizing a token I had created weeks earlier for unrelated purposes.
Expected behavior
When "Authenticate gh" is enabled for the local sandbox, I would expect one of the following:
GH_TOKENto be derived from the currently activegh auth statusaccount/session (respectinggh auth switch), not from some other cached credential, ORGH_TOKEN/GITHUB_TOKENenv var), this should be clearly surfaced to the user — e.g. via/sandboxor/env, showing which token/account is being exported into the sandbox and why, without requiring the user to manually diff PAT prefixes and check GitHub's org "Active tokens" page.Reproduction steps
gh auth login(OAuth device flow), confirm withgh auth statusthat the active session has broadreposcope.copilot, enable local sandboxing (/experimental onif needed, then/sandbox enable), leave "Authenticate gh" at its default (on).gh repo list <org> --visibility privateor inspect$GH_TOKEN.Additional context
/envand/sandboxdo not currently surface which specific token/account was selected forGH_TOKENin the sandbox, making this essentially undiagnosable without manual, external investigation (comparing token prefixes, checking org "Active tokens" pages, etc.).Configuring local sandbox settings→ Auth tab): "Authenticate gh: Export GH_TOKEN so that GitHub CLI ... works inside the sandbox without reaching its stored credentials (configuration directory or OS keychain), which the sandbox blocks." This explains that a substitute token is exported, but not how that substitute is selected when multiple credentials (OAuth session, GitHub App ghu_ token, cached fine-grained PATs) exist on the host.gh auth login), Over excessive permissions Request #953 (default OAuth grants excessive scope).Suggested improvement
/sandboxAuth tab or/env), exactly which token/account is currently selected for sandboxedgh/git operations, including its origin (activegh auth statussession vs. a manually-setGH_TOKEN/GITHUB_TOKENenv var vs. some other cached credential) and its repository scope.GH_TOKENfollow the currently activegh auth statusaccount by default, rather than silently preferring a possibly-staleGH_TOKEN/GITHUB_TOKENenv var or other cached credential.