Repository navigation
[Bug]: stale loopback proxy credentials survive the ocx claude base-URL rewrite #3004
Description
Client or integration
Claude Code
Area
CLI
Summary
buildClaudeEnv rewrites a stale loopback ANTHROPIC_BASE_URL to the current launch port but does not re-evaluate the Anthropic credential slots that were paired with the destination it just replaced.
The launcher already knows that a loopback ANTHROPIC_BASE_URL on a different port belongs to a previous opencodex launch: that is exactly the condition it logs and overwrites in src/cli/claude.ts (the Replacing stale opencodex ANTHROPIC_BASE_URL branch). An ANTHROPIC_AUTH_TOKEN inherited alongside it was minted by that other proxy, and after the rewrite it is carried into the new launch unchanged.
Two consequences, both on the subscription path:
- The token is not valid admission for this proxy. When the previous proxy required an admission key and this one does not, the launch is not merely mis-authenticated, it is silently pushed out of subscription mode.
setDefaultpreserves any non-empty value, so this proxy's own configured key is never injected.hostOwnsAuthenticationthen evaluates against a foreign token, soCLAUDE_CODE_PROVIDER_MANAGED_BY_HOSTis decided on stale evidence.
The subscription-preserving default immediately below the rewrite is explicit that setting ANTHROPIC_AUTH_TOKEN "disables claude.ai connectors and overrides the user's Claude login". A stale token reaching the child does precisely that: Claude Code authenticates as a host-managed provider instead of using the caller's own claude.ai OAuth, so native claude models no longer pass through with the caller's credential (wantsNativePassthrough in src/server/claude-messages.ts requires an sk-ant- credential on the request).
The existing PROXY_MARKER cleanup at the top of buildClaudeEnv and the inheritedTokenIsOurs check below both handle other shapes of this problem, which is why this specific pairing has stayed open: neither is keyed on the destination rewrite.
A genuine user sk-ant- credential must keep surviving the rewrite, because that is the credential native passthrough authenticates with.
Reproduction
- Start a proxy on port 19999 that requires an admission key, and launch
ocx claudefrom it so the environment carriesANTHROPIC_BASE_URL=http://127.0.0.1:19999plus that proxy'sANTHROPIC_AUTH_TOKEN. - From the same shell, start a second proxy on 10100 with no
apiKeysconfigured and runocx claude. - The launcher prints
Replacing stale opencodex ANTHROPIC_BASE_URL http://127.0.0.1:19999 with http://127.0.0.1:10100. - Inspect the spawned environment:
ANTHROPIC_AUTH_TOKENstill holds the 19999 proxy's key, even though this launch requires no admission key and should have stayed token-free in subscription mode.
Expected: credentials recognized as opencodex admission material are dropped when their paired destination is replaced, so the launch either injects this proxy's own key or stays token-free.
Version
2.36.0
Operating system
macOS 15.5 (platform-independent, env assembly only)
Provider and model
anthropic / claude-opus-5 (subscription OAuth path)
Logs or error output
Replacing stale opencodex ANTHROPIC_BASE_URL http://127.0.0.1:19999 with http://127.0.0.1:10100.Screenshots and supporting files
No response
Redacted configuration
{
"port": 10100,
"apiKeys": []
}
Activity
lidge-jun commentedon Aug 30, 2026
리뷰 · 우선순위 74 / 80
이 이슈는
ocx claude가 예전 루프백 프록시 주소를 새 포트로 바꿀 때, 그 주소에 짝지어져 있던 Anthropic 입장 토큰을 그대로 물려주는 버그를 보고한다. 지금dev(bb6a6fbdf)의src/cli/claude.tsbuildClaudeEnv는 “다른 포트의 루프백ANTHROPIC_BASE_URL은 예전 opencodex 실행이다”라고 이미 알고 주소를 덮어쓴다. 그런데ANTHROPIC_AUTH_TOKEN/ANTHROPIC_API_KEY는 그 분기에서 다시 보지 않는다.그 결과 두 가지가 겹친다. 첫째, 예전 프록시가 발급한 토큰은 이번 프록시 입장에는 쓸모가 없다. 둘째,
setDefault는 비어 있지 않은 값을 보존하므로 이번 프록시의 키가 있어도 주입되지 않고,hostOwnsAuthentication은 남의 토큰을 근거로CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST를 켠다. 입장 키가 필요 없는 프록시에서는 구독 OAuth로 남아야 하는데, Claude Code가 호스트 관리 공급자로 떠서 사용자 로그인·커넥터를 덮어쓴다. 주소 교체 바로 아래 “토큰을 넣으면 claude.ai를 끈다”는 주석이 경고하는 바로 그 상황이다.기존
PROXY_MARKER제거와inheritedTokenIsOurs검사는 다른 모양의 문제를 다루고, “주소를 바꿨다”는 조건에는 묶여 있지 않다. 그래서 이 짝이 비어 있었다. 사용자sk-ant-키는wantsNativePassthrough(src/server/claude-messages.ts) 때문에 주소 교체 후에도 살아남아야 한다. 재현 단계(19999에서 입장 키 있는 프록시 → 10100에서 키 없는 프록시)도 명확하다.착륙 PR은 이미 열려 있다. #3005가 같은 설명을 코드로 옮겼고, stale rewrite 분기 안에서
PROXY_MARKER/isProxyAdmissionSecret만 지운 뒤 회귀 테스트 세 개를 붙였다. types/config 대형 분할과 무관한 CLI 버그라 닫고 다시 열 대상이 아니다.이슈 본문 / buildClaudeEnv stale rewrite - 주소만 고치고 자격 증명 슬롯을 안 본다는 진단이 현재 HEAD와 맞다. 추가 재현 로그는 없어도 된다.
이슈 본문 / setDefault·hostOwnsAuthentication - 구독 경로에서 OAuth가 덮이는 인과도 코드 순서와 일치한다.
#3005 - 수정·테스트·Closes #3004가 이미 붙어 있다. CI만 남았다.
메인테이너의 판단이 필요한 지점
너의 추천
#3005 CI가 초록이면 머지하고 이 이슈는 자동 닫힘에 맡긴다. 별도 설계 이슈로 키울 필요는 없다. 중복 수정 PR이 오면 닫는다.
이 댓글은 grok-bot이 작성했습니다
fix(claude): drop admission credentials paired with a replaced stale …
lidge-jun commentedon Aug 30, 2026
Fixed on
devin c2778ca (#3005).The stale-destination rewrite in
buildClaudeEnvnow drops the credential slots paired with the replaced destination, but only for values matched byPROXY_MARKERorisProxyAdmissionSecret. A genuine usersk-ant-credential still survives the rewrite, because that is the credential native passthrough authenticates with.Three regression cases in
tests/claude-cli.test.tscover it: the stale admission token is dropped on a proxy with no configured keys, this proxy's own key is injected when it does configure one, and a usersk-ant-credential is preserved. Both new assertions were driven red against the unpatched launcher.Merged with
--adminon maintainer authority. Exact-head CI was green on 22 checks; the three failures were the repository-widepackage.json2.36.0 versus released tagv2.36.0version-line gate plus one unrelated macOS SIGHUP launcher case, both reproduced on pristineorigin/devwithout this change.fix(claude): drop admission credentials paired with a replaced stale …
fix(claude): drop admission credentials paired with a replaced stale …