fix(local): fail closed DNS bind names for credential-bearing destinations - #5042
Conversation
|
Note Currently processing new changes in this PR. This may take a few minutes, please wait... ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Advanced Run ID: 📒 Files selected for processing (4)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
✅ Deterministic PR hygiene checks passed. |
⏳ DRAFT
What to do
Review readiness checklist
10/10 boxes ticked. Automatic draft conversion failed. Please convert this pull request to a draft manually until every box above is ticked. |
리뷰 · 우선순위 73 / 80이 PR은 credential을 실어 나르는 로컬 destination이 DNS로 다시 풀릴 수 있는 bind 이름을 URL에 넣지 못하게 막습니다. 지금 변경 핵심은 테스트가 의도를 잘 고정합니다. 라인 (PR) localCredentialDestinationHostname - 메인테이너의 판단이 필요한 지점
너의 추천 이 댓글은 grok-bot이 작성했습니다 |
…tions probeHostname returns a DNS bind name unchanged, and the credential-bearing destination composers (localInferenceDestination, localManagementOrigin, resolveApiAccessBaseUrl) then embed that name in a URL the client dials with credentials attached. A hostname that re-resolves at dial time is a DNS-rebinding exfiltration path: the credential leaves for whatever the name resolves to then, not what it resolved to at compose time. localCredentialDestinationHostname keeps literal IPs as-is and fails closed to 127.0.0.1 for DNS names, so credential-bearing destinations only ever target a literal address. Display-only hosts keep the resolved name. Tests pin the fail-closed behavior for inference, management-origin, and API-access base URLs, plus the literal non-loopback IP path.
The fail-closed branch treated every non-literal bind name as a DNS bind, including `localhost`, and rewrote it to 127.0.0.1. That failed `ocx claude management discovery destination > a loopback or wildcard install keeps asking 127.0.0.1 on the public port`, which pins that a `localhost` install keeps writing `http://localhost:<port>` into its exported client configuration. The rewrite also bought nothing. RFC 6761 reserves `localhost` to loopback, so a second lookup cannot select a peer off this machine — the only outcome the fail-closed branch exists to prevent. `isLoopbackHostname` is already the encoding of "this name is loopback" in this module, so the carve-out reuses it rather than growing a second list. Also rebased onto current `dev`. Co-authored-by: luvs01 <luvs01@users.noreply.github.com>
1dc6d67 to
e6635e2
Compare
|
Pushed a follow-up commit (
The rewrite also bought nothing. RFC 6761 reserves One detail worth recording for the next reader: only The rest of the change is right and I am keeping it: a bind name the client re-resolves can point somewhere other than the listener, and a credential-bearing destination must not take that risk. |
|
Merging. The fail-closed reasoning is right and the A bind name the client re-resolves can point somewhere other than the listener, and a destination that carries a local credential must not take that risk — so a DNS bind degrading to a socket that refuses is the right failure. The carve-out reuses |
Summary
Follow-up to #491's direction: credential-bearing local destinations must not dial a re-resolvable name.
probeHostnamereturns a DNS bind name unchanged, and the credential-bearing destination composers (localInferenceDestination,localManagementOrigin,resolveApiAccessBaseUrl) then embed that name in a URL the client dials with credentials attached. A hostname that re-resolves at dial time is a DNS-rebinding exfiltration path: the credential leaves for whatever the name resolves to then, not what it resolved to at compose time.New
localCredentialDestinationHostnamekeeps literal IPs as-is and fails closed to127.0.0.1for DNS names, so credential-bearing destinations only ever target a literal address. Display-only hosts keep the resolved name.Test plan
bun test tests/lib/local-destinations.test.ts tests/server/api-access-endpoints.test.ts— 39 pass: DNS bind name fails closed to loopback for inference, management-origin, and API-access base URLs; literal non-loopback IPs still compose; wildcard/request-derived behavior unchanged.bun x tsc --noEmitclean.Declaration
Validation
tsc --noEmit)Risk
Notes
Summary by CodeRabbit
127.0.0.1.localhost, preserve their existing behavior.