Wei-Shaw/sub2api · error
xAI OAuth redirected to untrusted host
Error message
xAI OAuth redirected to untrusted host
What it means
After resolving each redirect target against the current URL, the flow re-validates it with safeXAIAuthURL. If the resolved absolute URL is not on a trusted xAI auth host, the request aborts with this error — an open-redirect guard so session cookies are never sent to a third party.
Source
Thrown at backend/internal/pkg/xai/sso_device.go:298
if len(data) > ssoMaxAuthBody {
return response.StatusCode, currentURL, nil, errors.New("xAI OAuth response exceeds 2 MiB")
}
if response.StatusCode < 300 || response.StatusCode > 399 {
return response.StatusCode, currentURL, data, nil
}
location := strings.TrimSpace(response.Header.Get("Location"))
if location == "" {
return response.StatusCode, currentURL, data, errors.New("xAI OAuth redirect missing Location")
}
base, _ := url.Parse(currentURL)
next, err := url.Parse(location)
if err != nil {
return response.StatusCode, currentURL, data, err
}
currentURL = base.ResolveReference(next).String()
if !safeXAIAuthURL(currentURL) {
return response.StatusCode, currentURL, data, errors.New("xAI OAuth redirected to untrusted host")
}
if response.StatusCode == http.StatusSeeOther || ((response.StatusCode == http.StatusMovedPermanently || response.StatusCode == http.StatusFound) && currentMethod != http.MethodGet && currentMethod != http.MethodHead) {
currentMethod = http.MethodGet
currentForm = nil
}
}
return 0, currentURL, nil, errors.New("xAI OAuth redirected too many times")
}
func seedSSOCookies(jar http.CookieJar, token string) {
if jar == nil {
return
}
for _, rawURL := range []string{SSOAccountsURL, OAuthIssuer + "/"} {
target, err := url.Parse(rawURL)
if err != nil {
continue
}View on GitHub (pinned to 073e92d171)
Solutions
- Inspect the redirect chain (log currentURL each hop) to find which host fell outside the trust set.
- If xAI legitimately added a host, extend the allowlist inside safeXAIAuthURL.
- Never disable the check to 'fix' the flow — an untrusted redirect with your session cookies is a credential leak.
- Verify you are not being proxied through something rewriting hosts (HTTP Host header rewrites).
Example fix
// before (conceptual allowlist)
func safeXAIAuthURL(u string) bool {
host := hostOf(u)
return host == "accounts.x.ai" || host == "xai.com"
}
// after (when xAI ships a new legit auth host)
func safeXAIAuthURL(u string) bool {
host := hostOf(u)
return host == "accounts.x.ai" || host == "xai.com" || host == "auth.x.ai"
} Defensive patterns
Strategy: try-catch
Validate before calling
if _, err := url.Parse(redirectTarget); err != nil {
return fmt.Errorf("bad redirect target: %w", err)
}
if !isExpectedXAIHost(hostOf(redirectTarget)) {
log.Printf("refusing off-host redirect to %s", redirectTarget)
} Try / catch
if err != nil {
if strings.Contains(err.Error(), "untrusted host") {
// either xAI added a host (update allowlist after verifying) or something hostile is in the chain — investigate, never bypass
securityLog.Alert(ctx, err)
}
return err
} Prevention
- Never disable the trusted-host check
- Log the offending URL for triage
- Track xAI auth-host changes in release notes / status page
When it happens
Trigger: A redirect Location pointing off-trusted-host: absolute URLs to other domains, or a relative resolution that lands on a non-auth xAI subdomain not in the trusted set. Also triggered by PTR-style tricks where ResolveReference yields an unexpected host.
Common situations: xAI adds a new auth host (e.g. a new SSO domain) not yet in safeXAIAuthURL's allowlist; third-party SSO (Okta etc.) inserted in the chain; malicious/compromised endpoint attempting cookie exfiltration (the guard doing its job).
Related errors
- xAI device verification did not reach consent page
- xAI device approval did not reach done page
- xAI OAuth redirect missing Location
- xAI OAuth redirected too many times
- xai sso unauthorized
AI-assisted analysis of Wei-Shaw/sub2api@073e92d171 (2026-08-15).
Data as JSON: /api/errors/fe7a7cd1e073c461.
Report an issue: GitHub.