[Bug] GITHUB_TOKEN in environment shadows user's gh CLI credentials

Open 💬 0 comments Opened Jul 6, 2026 by mauriaparker-kimedics

Bug Description

# Feedback: private-marketplace auth via a global GITHUB_TOKEN shadows users' own gh/git credentials Product: Claude Code (plugin marketplaces, private-repo auth + managed settings) Type: design feedback / bug-adjacent Related: github.com/anthropics/claude-code/issues/17201 (credential-helper path) — adjacent but distinct ## What happens To let a private plugin marketplace auto-update at startup, Claude Code reads a GITHUB_TOKEN / GH_TOKEN from the environment (per the docs' "Private repositories" section, which recommends setting it in .bashrc/.zshrc; in an enterprise setup it's injected via the managed remote-settings.json env block). That token is needed for exactly one internal Claude Code operation — the background git fetch of the marketplace repo when interactive auth can't run. But because it's the well-known GITHUB_TOKEN name placed in the general environment, it leaks into every subprocess — including the user's own gh CLI, which always prefers GH_TOKEN/GITHUB_TOKEN over its keyring login (not overridable). So a token provisioned for the marketplace silently hijacks the user's interactive GitHub auth. ## Why it's a problem The marketplace token and the account a developer uses gh with are frequently different identities — which is often intended: the marketplace is auto-updated by a shared/service token "not tied to anyone's account," while each developer runs gh as themselves. When those diverge (or the marketplace token is scoped only to the marketplace repo), the result is: - gh fails with confusing 404 Not Found on repos the user can access — because it's authenticating as the marketplace token, not the user. - It's silent and misdiagnosed: plain git still works (it uses the credential helper, ignores GITHUB_TOKEN), so users blame the repo name or their own access, not an injected token they never set. - In managed/fleet setups this hits every developer at once, and a single mis-scoped marketplace token breaks gh org-wide. Fundamentally: a credential for Claude Code's own internal fetch of one repo shouldn't be exported as a general-purpose GitHub credential into the user's shell, where it collides with their tooling. ## Suggested fixes (any one helps; roughly in order) 1. Don't route marketplace auth through the global environment. Scope the token to Claude Code's own git operation instead — e.g. a URL-scoped credential (http.<marketplace-url>.extraHeader), an ephemeral GIT_ASKPASS/credential.helper used only for the marketplace fetch subprocess — so it never lands in the environment gh and other tools inherit. 2. If an env var must be used, namespace it. Have Claude Code read a CC-specific variable for marketplace auth (e.g. CLAUDE_CODE_MARKETPLACE_TOKEN) rather than the shared GITHUB_TOKEN/GH_TOKEN that gh, GitHub Actions, and many other tools consume. 3. For managed settings specifically: provide a way to supply marketplace credentials to Claude Code without polluting the interactive shell environment devs inherit — and warn in the docs that injecting GITHUB_TOKEN via managed env will shadow every user's gh login. 4. At minimum, document the collision loudly. The docs currently recommend putting GITHUB_TOKEN in shell config, which is exactly the trap; a callout about the gh/tooling shadowing (and the "different account" failure mode) would save a lot of confused debugging. ## Repro (managed setup) 1. Managed settings inject GITHUB_TOKEN (a token scoped to the marketplace repo / a service account) via remote-settings.json's env. 2. Developer is logged into gh as themselves (gh auth login, keyring) and can access the org's repos. 3. gh repo view <org>/<repo>404 Not Found, while git ls-remote https://github.com/<org>/<repo> succeeds. Workaround today: gh() { command env -u GITHUB_TOKEN gh "$@"; }. ---

Environment Info

  • Platform: darwin
  • Terminal: Apple_Terminal
  • Version: 2.1.198
  • Feedback ID: 539a3b8e-faa7-4a23-8967-224939da272a

Errors

[]

View original on GitHub ↗