[Bug] GITHUB_TOKEN in environment shadows user's gh CLI credentials
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
[]