Skip to content

fix(oauth): restrict xAI discovery endpoint host and reject userinfo - #4065

Draft
chilung-cgu wants to merge 3 commits into
lidge-jun:devfrom
chilung-cgu:fix/xai-endpoint-validation
Draft

fix(oauth): restrict xAI discovery endpoint host and reject userinfo#4065
chilung-cgu wants to merge 3 commits into
lidge-jun:devfrom
chilung-cgu:fix/xai-endpoint-validation

Conversation

@chilung-cgu

@chilung-cgu chilung-cgu commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Summary

Verification

  • /home/ubuntu/.bun/bin/bun test tests/providers/xai/xai-endpoint-validation.test.ts — 5 pass / 0 fail.
  • /home/ubuntu/.bun/bin/bun test tests/test-layout.test.ts — 2 pass / 0 fail.
  • /home/ubuntu/.bun/bin/bun test tests/test-layout-tooling.test.ts — 15 pass / 0 fail.
  • /home/ubuntu/.bun/bin/bun test tests/server/server-xai-oauth-401-replay.test.ts — 8 pass / 0 fail.
  • /home/ubuntu/.bun/bin/bun run typecheck — exit 0.
  • /home/ubuntu/.bun/bin/bun run privacy:scan — passed.
  • git diff --check — clean.

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults.

Review readiness checklist

This PR stays in draft until every box below is ticked. Tick all four boxes once the requirements are met:

  • All CI tests are green on my local testing.

  • I pushed my PR to the latest dev commit.

  • I resolved all correct Codex and CodeRabbit findings.

  • My PR is ready for review.

Copilot AI lite review requested due to automatic review settings September 8, 2026 20:32
@github-actions github-actions Bot added the intake: hygiene-blocked Deterministic PR hygiene checks failed label Sep 8, 2026
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

⚠️ Deterministic hygiene checks failed.

  • unsponsored_surface — This changes an authentication, workflow, release-automation, or dependency surface. MAINTAINERS.md requires security review for these; ask a maintainer to apply maintainer-sponsored once they have reviewed it. Paths: src/oauth/xai.ts.

@github-actions github-actions Bot added the bug Something isn't working label Sep 8, 2026
@chilung-cgu
chilung-cgu force-pushed the fix/xai-endpoint-validation branch from 1a12f25 to 638b396 Compare September 8, 2026 20:32
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

⏳ DRAFT

  • hygiene: unsponsored_surface.

What to do

  • Fix unsponsored_surface — This changes an authentication, workflow, release-automation, or dependency surface. MAINTAINERS.md requires security review for these; ask a maintainer to apply maintainer-sponsored once they have reviewed it. Paths: src/oauth/xai.ts.

Review readiness checklist

  • ✅ All CI tests are green on my local testing.
  • ✅ I pushed my PR to the latest dev commit.
  • ✅ I resolved all correct Codex and CodeRabbit findings.
  • ✅ My PR is ready for review.

4/4 boxes ticked.

This pull request was already a draft. Its draft status will be preserved after every issue above is resolved.

@lidge-jun

Copy link
Copy Markdown
Owner

리뷰 · 우선순위 47 / 80

이 PR은 이슈 #4048을 닫는 xAI OAuth discovery 엔드포인트 검증 하드닝이다. 작성자는 chilung-cgu이고, 베이스는 dev, 헤드 커밋은 638b39650(브랜치 fix/xai-endpoint-validation), 현재 DRAFT이며 bug + intake: hygiene-blocked 라벨이 붙어 있다. 지금 로컬 dev HEAD는 ff524ae63(#4058 wp4), package 2.49.0이다. tip과 파일 충돌 면적은 src/oauth/xai.ts 한곳뿐이고, 같은 파일을 건드리는 형제 PR #4060(Retry-After/abort)도 열려 있다. types.ts/config.ts 분할 캠페인과는 무관해서 close-don't-rebase 대상이 아니다. 중복 구현 PR은 검색상 없다.

왜 지금 dev에서 의미가 있나. HEAD의 src/oauth/xai.ts 47–54행 validateXaiEndpoint는 discovery JSON이 돌려 준 authorization_endpoint / token_endpoint를 검사한 뒤, 그 URL로 refresh_token을 POST한다. 지금 검사는 “https이고 호스트가 x.ai이거나 *.x.ai로 끝나면 통과”라서 (1) https://evil.x.ai/token 같은 임의 서브도메인이 통과하고, (2) https://user:pass@auth.x.ai/...처럼 userinfo가 있으면 parsed.toString()이 그대로 남겨 fetch가 Authorization으로 바꿀 수 있다. discovery 자체는 고정 URL https://auth.x.ai/.well-known/openid-configuration(XAI_OAUTH_DISCOVERY_URL)에서 TLS로 가져오므로 심각도는 낮지만, 토큰이 나가는 마지막 관문이라 allow-list를 좁히는 편이 맞다. 이슈 본문·이전 grok-bot 이슈 리뷰(우선순위 42)와 측정이 같다.

이 PR이 하는 일은 딱 그 제안이다. TRUSTED_XAI_AUTH_HOSTSauth.x.aiaccounts.x.ai만 넣고, protocol이 https가 아니거나 username/password가 있거나 호스트가 집합 밖이면 throw한다. validateXaiEndpoint를 export해서 단위 테스트로 직접 친다. 새 파일 tests/providers/xai/xai-endpoint-validation.test.ts는 신뢰 호스트 통과, 임의 서브도메인/x.ai/api.x.ai 거절, userinfo 거절, http·타 도메인·auth.x.ai.attacker.com 거절, 그리고 fetch를 가짜로 바꿔 discovery의 token_endpoint가 evil.x.ai일 때 discoverXaiOAuthEndpoints가 거절하는지까지 다섯 케이스로 덮는다. 로컬 검증 주장(bun test 두 스위트, typecheck, privacy:scan)도 본문에 있다.

다만 머지 전에 게이트가 막고 있다. hygiene가 unsponsored_surface로 실패했고(src/oauth/xai.ts는 인증 표면), 봇이 DRAFT를 유지하며 maintainer-sponsored를 요구한다. 체크리스트도 헤드 SHA가 바뀐 뒤 0/4로 리셋된 상태다. #4060과 같은 파일을 고치므로, 둘 다 살리려면 한쪽을 먼저 랜딩한 뒤 다른 쪽을 리베이스해야 한다. allow-list에 accounts.x.ai를 넣은 선택은 이슈·progrok 참고와 맞고, 라이브 issuer는 auth.x.ai다. 미래에 xAI가 새 auth 호스트를 쓰면 로그인 전면 실패로 드러나는데, 그게 원하는 실패 모드다.

라인 47–54 (현 HEAD validateXaiEndpoint) - 이 PR이 정확히 고치는 느슨한 suffix/userinfo 구멍이다. 이슈 설명과 코드가 일치한다.

경로 TRUSTED_XAI_AUTH_HOSTS - auth.x.ai + accounts.x.ai 고정은 이슈 권고와 같다. api.x.ai를 의도적으로 거절하는 테스트도 있다.

경로 tests/.../xai-endpoint-validation.test.ts - 단위·discovery 통합 가짜 fetch까지 있어 회귀 방지가 충분하다. AUTH.X.AIauth.x.ai 정규화 기대는 URL 직렬화 동작과 맞다.

경로 hygiene unsponsored_surface - 인증 표면이라 외부 기여자는 maintainer-sponsored 없이 게이트를 통과할 수 없다. 코드 품질 문제가 아니라 프로세스 차단이다.

경로 #4060 형제 PR - 같은 src/oauth/xai.ts Retry-After/abort 하드닝과 겹친다. 랜딩 순서를 정하지 않으면 한쪽이 깨진다.

메인테이너의 판단이 필요한 지점

  • 보안 리뷰 후 maintainer-sponsored를 붙일지 (붙이지 않으면 게이트가 DRAFT를 유지함)
  • allow-list를 auth.x.ai만으로 더 좁힐지, 지금처럼 accounts.x.ai도 둘지
  • #4060과 이 PR 중 어느 쪽을 먼저 dev에 넣을지

너의 추천
내용상 받아도 된다. 작도 작고 테스트도 이슈 재현을 잘 덮는다. 다만 먼저 메인테이너가 보안 표면을 훑고 maintainer-sponsored를 붙인 뒤, 체크리스트 4칸을 다시 채우고, #4060과의 리베이스 순서를 정한 다음 머지하세요. 큐 맨 앞(wp 버그·릴리스)보다는 한 칸 뒤에 두면 충분하다. types/config 분할과 무관하고 close 대상도 아니다. #4048은 머지 키워드로 닫히면 된다.

이 댓글은 grok-bot이 작성했습니다

@coderabbitai

coderabbitai Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

It introduces a new test file that is not registered in the repo’s enforced test-layout fixtures and also risks credential leakage by including the raw (possibly userinfo-bearing) URL in the thrown error message.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR hardens xAI OAuth/OIDC discovery endpoint validation to reduce the risk of refresh tokens being sent to untrusted endpoints by pinning discovery-derived URLs to a small trusted host allow-list and rejecting URLs containing userinfo.

Changes:

  • Restrict validateXaiEndpoint to https://auth.x.ai and https://accounts.x.ai only, and reject embedded userinfo.
  • Add a new test suite covering trusted host allow-listing, scheme/domain rejection, and userinfo rejection.
File summaries
File Description
src/oauth/xai.ts Tightens discovery endpoint validation (trusted hosts + no userinfo).
tests/providers/xai/xai-endpoint-validation.test.ts Adds regression tests for the hardened endpoint validation and discovery rejection behavior.
Review details

Suppressed comments (1)

tests/providers/xai/xai-endpoint-validation.test.ts:13

  • New .test.ts files must resolve to a domain in scripts/test-layout/layout.json and be reflected in tests/fixtures/test-layout-expected.json (see tests/test-layout.test.ts and tests/test-layout-tooling.test.ts). This file’s basename (xai-endpoint-validation.test.ts) isn’t present in either explicit mapping/fixture and doesn’t match the providers/xai regex (which is grok-), so the full test suite will fail with an unresolved test file.
describe("xAI endpoint validation (#4048)", () => {
  • Files reviewed: 2/2 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/oauth/xai.ts Outdated
parsed.password ||
!TRUSTED_XAI_AUTH_HOSTS.has(host)
) {
throw new Error(`xAI OAuth discovery returned an unexpected endpoint: ${rawUrl}`);
Comment on lines +2 to +6
import {
discoverXaiOAuthEndpoints,
validateXaiEndpoint,
XAI_OAUTH_DISCOVERY_URL,
} from "../../../src/oauth/xai";
Pin xAI OAuth discovery endpoint validation to known trusted hosts
(auth.x.ai, accounts.x.ai) and reject endpoints containing embedded
userinfo.

Closes lidge-jun#4048
@chilung-cgu
chilung-cgu force-pushed the fix/xai-endpoint-validation branch from 8adb5fa to c48b802 Compare September 8, 2026 21:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working intake: hygiene-blocked Deterministic PR hygiene checks failed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants