Repository navigation
Blank ANTHROPIC_AUTH_TOKEN / ANTHROPIC_API_KEY in ug's Claude Code settings - #1185
luisscabral wants to merge 6 commits into
Conversation
Claude Code ranks ANTHROPIC_AUTH_TOKEN and ANTHROPIC_API_KEY above apiKeyHelper and the subscription login. When the user's shell still exports one of them, for example from another LLM gateway setup, `ug claude` hands it to Claude Code, which sends it to the AI Gateway instead of ug's token. Every request then fails with 401 "Credential was not sent or was of an unsupported type for this API" after ten retries, and `ug auth-token` is never called. `claude.launch()` now removes both variables before any launch path (default, relayed, smart routing) starts Claude Code, and warns on stderr when it drops a non-empty value. Co-authored-by: Isaac <no-reply@databricks.com>
…wing-anthropic-env
Rework the fix after review: instead of removing ANTHROPIC_AUTH_TOKEN and ANTHROPIC_API_KEY from the environment at launch, ug now writes both as empty strings in the settings env block it already owns, next to ANTHROPIC_BASE_URL. Claude Code applies settings env over the shell, so a credential left by another LLM gateway setup can no longer outrank apiKeyHelper. Because the block is mirrored into the OS-managed file, this also covers a bare `claude`, and `ug revert` removes the keys with the rest of ug's fields. The user's shell is left untouched. `ug claude` keeps a one-line stderr note when either variable is set. The e2e and user-agent tests pass their token through DATABRICKS_BEARER, since ug's settings now blank ANTHROPIC_API_KEY. Co-authored-by: Isaac <no-reply@databricks.com>
Scripts that authenticated Claude Code with a PAT in ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEY now get those values blanked by ug's settings. The warning tells them to set DATABRICKS_BEARER, which ug's apiKeyHelper returns as is. Co-authored-by: Isaac <no-reply@databricks.com>
|
/ug-review |
Polly AI ReviewBlocking issuesNone verified. Security vulnerabilitiesNone verified. The warning prints variable names, not credential values; the new warning helper does not mutate Non-blocking notes
ApproachThe approach is sound. It reuses settings ownership, managed-file composition, and revert handling rather than introducing launch-time environment mutation. SummaryDiff size (computed): 8 files; +149 / -6 lines (155 changed text lines); 0 binary files.
Shares use additions + deletions, including generated text and lockfiles. Binary files have no line count. Tests include fixtures/helpers under test paths and colocated test/spec files; categories are path-based, not coverage measurements. ChangesThe change prevents inherited Anthropic credentials from overriding ug’s configured authentication. It adds empty credential settings, an actionable stderr warning, ownership documentation, focused coverage, and necessary authentication-input repairs in existing tests. The size is proportional to the outcome. No unnecessary implementation scaffolding or dependency changes were found. TestsTest-by-test assessmentStatic review only; no tests were executed. The PR’s reported execution results were not independently reproduced. Context was checked against the trusted checkout; the supplied base/head commit objects were unavailable there.
Existing managed-file lifecycle coverage checks write-to-revert baseline restoration. The live test uniquely checks Claude’s external authentication precedence; unit assertions alone cannot establish it. Live relayed authentication remains unverified, but no concrete defect or additional necessary coverage gap was established. ScopeAll changes support preventing inherited credentials from shadowing ug authentication. The existing E2E input changes repair setup affected by that behavior. No unrelated changes were found. Automated review by Polly · workflow run |
…wing-anthropic-env
- The launch warning always names both variables, without singular and plural variants. - `ug doctor` reuses SHADOWING_CREDENTIAL_ENV_VARS and the launch warning's wording instead of telling users to unset the variables, which ug's settings now blank for Claude Code. - Fold the shell-credentials scenario into the existing headless prompt-argument journey instead of a separate live test. - Keep one launch warning test: the warning runs before the relayed branch. Register OAUTH_TOKEN so the warning test cleans it up. - Shorten the constant's comment. Co-authored-by: Isaac <no-reply@databricks.com>
|
Polly's notes are addressed in f793068: |
|
/integration-tests |
|
/integration-test |
|
Fork integration failure on f793068: https://github.com/databricks/unity-gateway/actions/runs/39632293275 |
1 similar comment
|
Fork integration failure on f793068: https://github.com/databricks/unity-gateway/actions/runs/39632293275 |
What
ug now writes
ANTHROPIC_AUTH_TOKENandANTHROPIC_API_KEYas empty strings in the Claude Code settingsenvblock it already owns, next toANTHROPIC_BASE_URL. A credential left in the user's shell by another LLM gateway setup can no longer replace ug's credential.ug claudeprints one stderr line when either variable is set.This replaces the first version of this PR, which removed the variables from the environment at launch. Following review, the user's environment is no longer touched.
Why
Claude Code ranks
ANTHROPIC_AUTH_TOKENandANTHROPIC_API_KEYaboveapiKeyHelperand the subscription login (authentication precedence). The order is fixed: it applies even whenapiKeyHelperis in OS-managed settings. ug already overrides the shell'sANTHROPIC_BASE_URLthrough its settings, so a shell set up for another gateway keeps its token but gets the Databricks URL. Claude Code then sends that token to the AI Gateway, retries ten times over about three minutes, and fails with:ug auth-tokenis never called.ug doctoralready warns about these variables, but nothing prevented the failure.How
render_overlayadds both keys as""to theenvblock. They become ug-owned keys like the rest of that block:~/.claude/ucode-settings.json;claudeis covered too;ug revert.launch()no longer changesos.environ. It warns on stderr when a non-empty value is present, so headless stdout stays machine-readable. The warning points scripts that authenticate with a PAT atDATABRICKS_BEARER, whichug auth-tokenreturns as is.ug doctorreuses the same constant and wording, instead of telling users to unset the variables.AGENTS.md's "Fields ug manages" table lists the two keys.Things reviewers should know:
envto its own process, so its Bash tool, hooks and MCP servers see""(checked with the Bash tool). The user's shell and other tools keep their values.ANTHROPIC_API_KEYorANTHROPIC_AUTH_TOKENin the OS-managed file, ug now replaces it like any other ug-owned leaf (see the new managed-file test).DATABRICKS_BEARER,DATABRICKS_BEARER_COMMANDand--use-patalready serve that case.Tests
tests/test_agent_claude.py:DATABRICKS_BEARERhint, leavesos.environunchanged, and stays silent for empty values.tests/integration/test_ug_claude_headless.py:test_ug_claude_headless_prompt_argumentnow runs with both variables set to a foreign key in the shell. It must still answer through the gateway, and stderr must report both as ignored. It is the Claude case of the runner's headless subset, so it also runs on Windows and the other Claude versions that subset covers.tests/test_doctor.py: the check names the variables, points atDATABRICKS_BEARERand no longer says to unset them.tests/test_e2e.pyandtests/test_e2e_user_agent.py: these passed their token asANTHROPIC_API_KEYalongside ug's settings, which ug now blanks, so they pass it throughDATABRICKS_BEARERand the generatedapiKeyHelperinstead.uv run pytest --basetemp=/tmp/ugtgives 5042 passed and 12 failed. The same 12 tests fail onmainat da363b2 on this machine:test_e2e_user_agent.py, which time out before reaching their capture server because this machine's OS-managed Claude settings pin another gateway URL;test_skills.py;test_smart_router.py.ruff check,ruff format --check,ty check src/andtests/test_integration_contract.pypass.apiKeyHelper:ANTHROPIC_AUTH_TOKENin the shell fails with the 401 above, after 11 attempts.--settings '{"env":{"ANTHROPIC_AUTH_TOKEN":"","ANTHROPIC_API_KEY":""}}'and both variables set in the shell, it answers, and the Bash tool reports both as empty.envvalue also beats the same shell variable forANTHROPIC_BASE_URL.ANTHROPIC_API_KEYalone did not break that headless run;ANTHROPIC_AUTH_TOKENdid.UCODE_TEST_WORKSPACE;This pull request and its description were written by Isaac.