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

  1. Inspect the redirect chain (log currentURL each hop) to find which host fell outside the trust set.
  2. If xAI legitimately added a host, extend the allowlist inside safeXAIAuthURL.
  3. Never disable the check to 'fix' the flow — an untrusted redirect with your session cookies is a credential leak.
  4. 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

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


AI-assisted analysis of Wei-Shaw/sub2api@073e92d171 (2026-08-15). Data as JSON: /api/errors/fe7a7cd1e073c461. Report an issue: GitHub.