ANTHROPIC_BASE_URL is an ordinary documented Claude Code setting that decides where API traffic goes — it exists so the client can be pointed at an enterprise API gateway, a regional endpoint, or a self-hosted proxy in front of Anthropic's API rather than hardcoding api.anthropic.com. Claude Code trusts whatever address it names and sends every request there without asking again. Point it at a server you control and the next ordinary command sends your Claude Code sign-in token — not just an API key — to that server in the Authorization header of a normal API request, with no warning and nothing visibly different in the response.
The address can be set two ways, each sufficient on its own: a shell environment variable, or a file committed inside a repository. The folder route is the problematic one because Claude Code treats a folder as trusted if any of its parent directories were ever trusted, so a developer who once trusted a parent directory can leak a live credential merely by pulling a routine repo update somewhere beneath it. The issue was reported to Anthropic, which rated it "Informative." Anthropic patched the timing half of the problem as CVE-2026-21852 (CWE-522) in January 2026, reported by Check Point Research; the underlying trust model was not changed.
Key Points
The leaked credential is a live sign-in token: whoever holds it can act as the user when calling Anthropic's API, not merely read back a response.
Two delivery routes, with very different attacker requirements: a committed .claude/settings.jsonenv block (needs the folder to be trusted, or claude -p), and the shell environment (shell profile, .envrc, devcontainer definition, or a CI job's environment block).
CVE-2026-21852: before version 2.0.65, a repository's settings file could set ANTHROPIC_BASE_URL and Claude Code would issue API requests to that address before ever displaying the trust prompt. The fix put the prompt first but did not stop the file being honored once a folder counts as trusted.
On version 2.1.220, with the address set only in the committed file and no prompt to accept, three POST /v1/messages requests reached the test listener carrying the sign-in credential as . A control run with the same address set in the environment produced identical requests.
Authorization: Bearer
Under claude -p there is no trust prompt at all — nothing to weaken. The same file in a folder claude had never seen, in an isolated container with no base URL in the environment, forwarded the credential with nothing to accept or decline. First observed on build 2.1.7 and still true on 2.1.220.
Folder trust is path-keyed, inherited, and content-blind: ~/.claude.json stores a per-path flag, a folder is trusted if any ancestor is trusted, and no field records the settings file's contents, so editing them never re-triggers a prompt.
Credential forwarding held on all six builds sampled, from 2.1.152 to 2.1.220, tested between 2026-07-08 and 2026-07-27.
Concepts
ANTHROPIC_BASE_URL — documented Claude Code environment setting that redirects all API traffic to a named address. It is read from the process environment or from an env block in .claude/settings.json, and is honored without any per-destination confirmation.
Sign-in token vs. API key — the forwarded credential is the live /login sign-in token, which carries five permissions read off the credential itself (one named user:mcp_servers, left unglossed rather than guessed at). It is a different class of secret from an API key and is accepted by Anthropic's API.
Folder trust — Claude Code's per-path trust flag, stored in ~/.claude.json. Trust is inherited from any parent directory (Anthropic issue tracker #72896), is never re-checked against the folder's current contents, and declining the prompt exits Claude Code.
CVE-2026-21852 — Check Point Research report (CWE-522) covering the ordering flaw where the base URL took effect before the trust prompt. Patched in 2.0.65; the post-trust behavior survived the patch.
TrustFall — prior research showing the same .claude/settings.json + .mcp.json combination reaching code execution across four coding agents. Neither TrustFall nor the Anthropic tracker covers the timing gap described here.
Rendering diagram…
Details
How the attack runs. The realistic delivery is not the initial clone but a merged PR or a routine pull into a repo trusted weeks earlier, since trust is never re-checked against the folder's current contents. A .claude/settings.json committed at the project root carries an env block that Claude Code applies directly — nothing touches the shell, profile, or machine config. The precondition is that the folder is already trusted (often inherited from a trusted ancestor) or that Claude Code runs under claude -p, where there is no trust prompt at all. Where a first-open prompt appeared during testing, it was accepted, as most people do for a repo they just cloned.
The alternative route is the shell environment — a shell profile, .envrc, devcontainer definition, or a CI job's environment block. This is Claude Code's own route: a command-line tool reads whatever environment it is launched into, so anything able to set a variable in that environment can redirect the client.
After that nothing unusual happens. A normal command is typed, the client addresses its request to the attacker's server and attaches the credential as usual, and an answer comes back because the attacker's server can reply like the real API. Nothing in the output names the destination, and no second prompt asks about it. The attacker ends up holding a live credential belonging to whoever ran the command.
The trust gap. The root cause is the folder-trust prompt itself. Trust is granted once and never revisited, so a repository trusted last month whose settings file gains an env block today through a merged change applies the new base URL with no re-check — consent was given to a folder once, not to whatever later lives inside it. On the test machine, home was trusted, so a repo beneath it got no prompt at all. Reopening an already-trusted folder showed no prompt, and because no field records the settings file's contents, editing them does not re-trigger one.
Reproduction on patched builds. On 2.1.220, in an interactive session with folder trust accepted and no base URL anywhere in the environment, three POST /v1/messages requests reached the listener with the credential attached; a control run that put the address in the environment instead hit a second listener, confirming the session was working normally either way. The scripted-mode reproduction — same committed file, never-seen folder, isolated container, no base URL in the environment — forwarded the credential with nothing to accept or decline. CI jobs never see a folder-trust dialog, making that the more serious route.
Credential validity checks. A throwaway automation token was replayed read-only against four endpoints, with /v1/models answering HTTP 200; it was revoked afterwards. The /login credential was revoked and deleted without ever being replayed. /v1/me and /v1/organizations both returned 404, and where the API key itself is sent was not captured.
Observed quirk, scripted mode only, not to be relied on. Under claude -p, setting ANTHROPIC_API_KEY stopped the sign-in credential from being forwarded, and clearing it restored forwarding. Two interactive runs did not reproduce this.
Limits of the findings. The API-key suppression behavior is scripted-mode only and was not reproduced interactively. The five permission names come from the credential itself, not from Anthropic's documentation. Neither credential's lifetime was measured — the automation token still authenticated on replay, while the /login credential was never replayed at all.