zeroclaw-labs/zeroclaw · error · anyhow::Error

xAI OAuth discovery returned non-HTTPS {label}

Error message

xAI OAuth discovery returned non-HTTPS {label}

What it means

require_trusted_endpoint enforces that every endpoint xAI's OAuth discovery document advertises (authorization_endpoint, token_endpoint, device_authorization_endpoint) uses HTTPS. It fires when the endpoint URL parses but its scheme is http:, which would send authorization codes, tokens, and client secrets in cleartext. This is a deliberate security guard, not a connectivity problem.

Source

Thrown at crates/zeroclaw-providers/src/auth/xai_oauth.rs:558

}

fn decode_jwt_payload(token: &str) -> Option<serde_json::Value> {
    let payload = token.split('.').nth(1)?;
    let bytes = base64::engine::general_purpose::URL_SAFE_NO_PAD
        .decode(payload)
        .ok()
        .or_else(|| {
            base64::engine::general_purpose::URL_SAFE
                .decode(payload)
                .ok()
        })?;
    serde_json::from_slice(&bytes).ok()
}

fn require_trusted_endpoint(endpoint: &str, label: &str) -> Result<String> {
    let url = reqwest::Url::parse(endpoint).with_context(|| format!("Invalid xAI {label}"))?;
    if url.scheme() != "https" {
        anyhow::bail!("xAI OAuth discovery returned non-HTTPS {label}");
    }
    let host = url.host_str().unwrap_or_default();
    if host == "x.ai" || host.ends_with(".x.ai") {
        return Ok(endpoint.to_string());
    }
    anyhow::bail!("xAI OAuth discovery returned untrusted {label}: {endpoint}")
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn authorize_url_contains_xai_oauth_params() {
        let pkce = PkceState {
            code_verifier: "verifier".into(),
            code_challenge: "challenge".into(),
            state: "state".into(),

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Remove any local override of xAI discovery/authorization/token endpoints and use the official https endpoints on x.ai
  2. Check for corporate proxies or SSL-inspection middleboxes rewriting x.ai responses and bypass them for x.ai
  3. Verify the discovery document actually returns https endpoints: curl the xAI well-known URL and inspect the endpoint fields
  4. For local testing use an https mock with a trusted certificate; never downgrade to http with real xAI credentials
Defensive patterns

Strategy: try-catch

Validate before calling

// If you feed endpoints into the flow, reject http early on your side too
if let Some(endpoint) = overridden_endpoint {
    let url = reqwest::Url::parse(endpoint)?;
    if url.scheme() != "https" {
        anyhow::bail!("refusing non-HTTPS xAI endpoint: {endpoint}");
    }
}

Try / catch

match start_device_code_flow(&ctx).await {
    Ok(flow) => { /* show user_code */ }
    Err(e) if e.to_string().contains("non-HTTPS") => {
        // security guard tripped: surface loudly, never auto-retry,
        // audit proxies/DNS before the next attempt
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Any xAI OAuth flow step that consumes discovery (fetch_oauth_discovery, fetch_device_code_discovery, exchange_code_for_tokens, start_device_code_flow, poll_device_code_tokens) hits an endpoint whose URL starts with http:// instead of https://, whether from the fetched discovery JSON or a local override.

Common situations: Debugging against a local http mock of xAI auth; a proxy or captive portal rewriting the discovery response; a tampered or attacker-controlled discovery document; manual endpoint override to an http URL.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/59ece6b471d2b67c. Report an issue: GitHub.