Where
src/oauth/xai.ts lines 47-54 (validateXaiEndpoint), on dev:
const host = parsed.hostname.toLowerCase();
if (parsed.protocol !== "https:" || (host !== "x.ai" && !host.endsWith(".x.ai"))) {
throw new Error(...);
}
return parsed.toString();
Problem
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.
Both measured on Node 24.
Fix
Pin to the known auth hosts and reject userinfo:
const TRUSTED = new Set(["auth.x.ai", "accounts.x.ai"]);
if (parsed.protocol !== "https:" || parsed.username || parsed.password || !TRUSTED.has(host)) throw ...;
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).
Where
src/oauth/xai.tslines 47-54 (validateXaiEndpoint), ondev:Problem
Two gaps in the endpoint trust check applied to the OIDC discovery response, which is the URL that then receives the
refresh_tokenin a POST body:https://anything.x.ai/tokenpasses. If the discovery document were ever tampered with (or a subdomain compromised), the refresh token would be posted there.new URL()preserves userinfo, andparsed.toString()returns it:https://u:p@auth.x.ai/oauth2/tokenpasses unchanged, andfetchwill turn the userinfo into anAuthorizationheader on the request.Both measured on Node 24.
Fix
Pin to the known auth hosts and reject userinfo:
auth.x.aiis the live issuer perhttps://auth.x.ai/.well-known/openid-configuration(checked 2026-09-09);accounts.x.aiis 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.mdD6).