{"record":{"id":"edfff7eee06bdc5f","repo":"Hmbown/CodeWhale","slug":"oidc-discovery-returned-credentials-in-field","errorCode":null,"errorMessage":"OIDC discovery returned credentials in {field}","messagePattern":"OIDC discovery returned credentials in (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/tui/src/oauth.rs","lineNumber":697,"sourceCode":"    field: &str,\n    issuer: &str,\n) -> Result<String> {\n    let endpoint = endpoint\n        .as_deref()\n        .map(str::trim)\n        .filter(|endpoint| !endpoint.is_empty())\n        .with_context(|| format!(\"OIDC discovery missing {field}\"))?;\n    let parsed = reqwest::Url::parse(endpoint)\n        .with_context(|| format!(\"OIDC discovery returned an invalid {field}\"))?;\n    if !matches!(parsed.scheme(), \"http\" | \"https\") {\n        bail!(\"OIDC discovery returned unsupported {field} scheme\");\n    }\n    let issuer = oauth_endpoint_url(issuer).context(\"OIDC issuer is not a trusted URL\")?;\n    if issuer.scheme() == \"https\" && parsed.scheme() != \"https\" {\n        bail!(\"OIDC discovery attempted to downgrade {field} from HTTPS\");\n    }\n    if !parsed.username().is_empty() || parsed.password().is_some() {\n        bail!(\"OIDC discovery returned credentials in {field}\");\n    }\n    if parsed.origin() != issuer.origin() {\n        bail!(\"OIDC discovery returned {field} on a different origin than the issuer\");\n    }\n    let _ = oauth_endpoint_url(parsed.as_str())?;\n    Ok(endpoint.to_string())\n}\n\n/// Documented-path endpoints for a provider row, no discovery.\nfn fallback_oauth_endpoints(params: &OAuthProviderParams, issuer: &str) -> OAuthEndpoints {\n    OAuthEndpoints {\n        device_authorization_endpoint: params\n            .device_code_path\n            .map(|path| format!(\"{}/{}\", issuer.trim_end_matches('/'), path)),\n        token_endpoint: format!(\"{}/{}\", issuer.trim_end_matches('/'), params.token_path),\n    }\n}\n","sourceCodeStart":679,"sourceCodeEnd":715,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/oauth.rs#L679-L715","documentation":"A discovered OAuth endpoint URL embeds userinfo credentials (a username or password component, e.g. https://user:pass@host/path). Embedding credentials in an OAuth endpoint URL leaks them into logs and discovery documents and is never a legitimate configuration, so validation rejects it.","triggerScenarios":"validate_discovered_oauth_endpoint finding parsed.username() non-empty or parsed.password() Some on the {field} endpoint URL.","commonSituations":"Someone pasting a URL with basic-auth credentials (https://user:pass@host) into an IdP endpoint setting; a templated endpoint URL left with credential placeholders filled in; misconfigured reverse proxy docs examples copied verbatim.","solutions":["Remove the username/password from the endpoint URL in the IdP configuration.","If the endpoint genuinely requires auth, use proper OAuth client authentication (client_id/secret in the token request), not URL userinfo.","Rotate any credentials that were embedded in the URL, since they may have been logged.","Re-check the discovery document after fixing and confirm the endpoints are plain host[:port]/path URLs."],"exampleFix":"// before\n\"token_endpoint\": \"https://admin:s3cret@auth.example.com/token\"\n// after\n\"token_endpoint\": \"https://auth.example.com/token\"","handlingStrategy":"validation","validationCode":"if let Ok(url) = reqwest::Url::parse(endpoint) {\n    if !url.username().is_empty() || url.password().is_some() {\n        eprintln!(\"endpoint URL contains embedded credentials — remove and rotate them\");\n    }\n}","typeGuard":"fn no_url_credentials(s: &str) -> bool {\n    reqwest::Url::parse(s).map(|u| u.username().is_empty() && u.password().is_none()).unwrap_or(false)\n}","tryCatchPattern":null,"preventionTips":["Never paste basic-auth URLs (user:pass@host) into IdP endpoint settings.","Use OAuth client authentication (client_id/client_secret) instead of URL userinfo.","Rotate any credential that has ever been embedded in a URL.","Lint config files for '@' userinfo in endpoint URLs."],"tags":["oauth","security","url","credentials","discovery"],"backgroundTag":"invalid-url-format","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T21:17:16.096Z"}