{"record":{"id":"59ece6b471d2b67c","repo":"zeroclaw-labs/zeroclaw","slug":"xai-oauth-discovery-returned-non-https-label","errorCode":null,"errorMessage":"xAI OAuth discovery returned non-HTTPS {label}","messagePattern":"xAI OAuth discovery returned non-HTTPS (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-providers/src/auth/xai_oauth.rs","lineNumber":558,"sourceCode":"}\n\nfn decode_jwt_payload(token: &str) -> Option<serde_json::Value> {\n    let payload = token.split('.').nth(1)?;\n    let bytes = base64::engine::general_purpose::URL_SAFE_NO_PAD\n        .decode(payload)\n        .ok()\n        .or_else(|| {\n            base64::engine::general_purpose::URL_SAFE\n                .decode(payload)\n                .ok()\n        })?;\n    serde_json::from_slice(&bytes).ok()\n}\n\nfn require_trusted_endpoint(endpoint: &str, label: &str) -> Result<String> {\n    let url = reqwest::Url::parse(endpoint).with_context(|| format!(\"Invalid xAI {label}\"))?;\n    if url.scheme() != \"https\" {\n        anyhow::bail!(\"xAI OAuth discovery returned non-HTTPS {label}\");\n    }\n    let host = url.host_str().unwrap_or_default();\n    if host == \"x.ai\" || host.ends_with(\".x.ai\") {\n        return Ok(endpoint.to_string());\n    }\n    anyhow::bail!(\"xAI OAuth discovery returned untrusted {label}: {endpoint}\")\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn authorize_url_contains_xai_oauth_params() {\n        let pkce = PkceState {\n            code_verifier: \"verifier\".into(),\n            code_challenge: \"challenge\".into(),\n            state: \"state\".into(),","sourceCodeStart":540,"sourceCodeEnd":576,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-providers/src/auth/xai_oauth.rs#L540-L576","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Remove any local override of xAI discovery/authorization/token endpoints and use the official https endpoints on x.ai","Check for corporate proxies or SSL-inspection middleboxes rewriting x.ai responses and bypass them for x.ai","Verify the discovery document actually returns https endpoints: curl the xAI well-known URL and inspect the endpoint fields","For local testing use an https mock with a trusted certificate; never downgrade to http with real xAI credentials"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// If you feed endpoints into the flow, reject http early on your side too\nif let Some(endpoint) = overridden_endpoint {\n    let url = reqwest::Url::parse(endpoint)?;\n    if url.scheme() != \"https\" {\n        anyhow::bail!(\"refusing non-HTTPS xAI endpoint: {endpoint}\");\n    }\n}","typeGuard":null,"tryCatchPattern":"match start_device_code_flow(&ctx).await {\n    Ok(flow) => { /* show user_code */ }\n    Err(e) if e.to_string().contains(\"non-HTTPS\") => {\n        // security guard tripped: surface loudly, never auto-retry,\n        // audit proxies/DNS before the next attempt\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Never override xAI OAuth endpoints with http URLs, even for local tests","Use https mocks with trusted certificates when testing the flow locally","Watch for SSL-inspection proxies rewriting x.ai discovery responses","Treat this error as a security signal, not a transient failure - do not blind-retry"],"tags":["oauth","xai","https","security","rust"],"backgroundTag":"insecure-scheme-endpoint-rejected","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}