You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
oauth/xai: validateXaiEndpoint accepts any *.x.ai subdomain and URLs with embedded userinfo #4048
Two gaps in the endpoint trust check applied to the OIDC discovery response, which is the URL that then receives the refresh_token in a POST body:
Suffix-only host match: https://anything.x.ai/token passes. If the discovery document were ever tampered with (or a subdomain compromised), the refresh token would be posted there.
new URL() preserves userinfo, and parsed.toString() returns it: https://u:p@auth.x.ai/oauth2/token passes unchanged, and fetch will turn the userinfo into an Authorization header on the request.
auth.x.ai is the live issuer per https://auth.x.ai/.well-known/openid-configuration (checked 2026-09-09); accounts.x.ai is the second host the progrok reference implementation allow-lists.
Severity: low (discovery is fetched over TLS from a fixed host), filed as hardening. Found while porting this module into ima2-gen (devlog 260909_grok_native_oauth/001_opencodex_port_spec.md D6).
이 이슈는 OIDC discovery가 돌려 준 token/authorization URL을 검사하는 validateXaiEndpoint가 너무 느슨하다는 하드닝 요청입니다. 지금 dev HEAD cfff026src/oauth/xai.ts 47–54행은 https이고 호스트가 x.ai이거나 *.x.ai로 끝나면 통과시킨 뒤 parsed.toString()을 그대로 반환합니다.
두 구멍이 있습니다. (1) 접미사만 보면 https://anything.x.ai/token도 통과합니다. discovery가 조작되거나 서브도메인이 뚫리면 refresh_token이 그쪽으로 POST됩니다. (2) new URL은 userinfo를 유지하고 toString()도 유지합니다. https://u:p@auth.x.ai/oauth2/token이 그대로 나가면 fetch가 userinfo를 Authorization으로 바꿀 수 있습니다. 작성자도 severity low로 적었고, discovery 자체는 고정 호스트 https://auth.x.ai/.well-known/openid-configuration에서 TLS로 가져옵니다.
제안은 허용 호스트를 auth.x.ai / accounts.x.ai로 고정하고 username/password가 있으면 거절하는 것입니다. 라이브 issuer가 auth.x.ai인 점, progrok 참고 구현이 accounts.x.ai도 넣는 점과 맞습니다. 다만 미래에 xAI가 새 auth 호스트를 추가하면 여기 allow-list를 고쳐야 합니다. #4045–#4047과 같은 파일이지만, 긴급도는 더 낮습니다.
Activity
lidge-jun commentedon Sep 8, 2026
리뷰 · 우선순위 42 / 80
이 이슈는 OIDC discovery가 돌려 준 token/authorization URL을 검사하는
validateXaiEndpoint가 너무 느슨하다는 하드닝 요청입니다. 지금devHEAD cfff026src/oauth/xai.ts47–54행은 https이고 호스트가x.ai이거나*.x.ai로 끝나면 통과시킨 뒤parsed.toString()을 그대로 반환합니다.두 구멍이 있습니다. (1) 접미사만 보면
https://anything.x.ai/token도 통과합니다. discovery가 조작되거나 서브도메인이 뚫리면 refresh_token이 그쪽으로 POST됩니다. (2)new URL은 userinfo를 유지하고toString()도 유지합니다.https://u:p@auth.x.ai/oauth2/token이 그대로 나가면 fetch가 userinfo를 Authorization으로 바꿀 수 있습니다. 작성자도 severity low로 적었고, discovery 자체는 고정 호스트https://auth.x.ai/.well-known/openid-configuration에서 TLS로 가져옵니다.제안은 허용 호스트를
auth.x.ai/accounts.x.ai로 고정하고 username/password가 있으면 거절하는 것입니다. 라이브 issuer가auth.x.ai인 점, progrok 참고 구현이accounts.x.ai도 넣는 점과 맞습니다. 다만 미래에 xAI가 새 auth 호스트를 추가하면 여기 allow-list를 고쳐야 합니다. #4045–#4047과 같은 파일이지만, 긴급도는 더 낮습니다.라인 47–54 · validateXaiEndpoint -
endsWith(".x.ai")와 userinfo 미검사가 핵심입니다. 측정·설명과 코드가 일치합니다.경로 discoverXaiOAuthEndpoints - discovery JSON의 endpoint 문자열만 이 함수를 탑니다. 고정 discovery URL 자체는 이미 안전합니다.
경로 allow-list 유지비 - 호스트를 좁히면 보안은 좋아지고, xAI가 엔드포인트를 옮기면 로그인 전면 실패로 드러납니다. 그게 원하는 실패 모드인지 정하면 됩니다.
메인테이너의 판단이 필요한 지점
auth.x.ai만으로 할지accounts.x.ai까지 넣을지너의 추천
받아 두되 큐 앞에는 두지 마세요. #4045/#4047 같은 동작 버그 PR이 열린 뒤에 같은 파일 후속으로 넣거나, 작은 단독 PR로
help wanted에 두면 됩니다. types/config 분할과 무관하고 close 대상도 아닙니다.이 댓글은 grok-bot이 작성했습니다
fix(oauth): restrict xAI discovery endpoint host and reject userinfo
fix(oauth): restrict xAI discovery endpoint host and reject userinfo
lidge-jun commentedon Sep 9, 2026
Fixed on
devvia #4094 at 4a08c75.devlog: plan the xAI OAuth retry hardening unit (lidge-jun#4045, lidg…
oauth/xai: pin discovery endpoints to trusted auth hosts and reject u…
devlog: plan the xAI OAuth retry hardening unit (lidge-jun#4045, lidg…
oauth/xai: pin discovery endpoints to trusted auth hosts and reject u…