{"record":{"id":"9f9cdd209f239a5b","repo":"Hmbown/CodeWhale","slug":"context-returned-a-verification-uri-with-embedded","errorCode":null,"errorMessage":"{context} returned a verification URI with embedded credentials","messagePattern":"(.+?) returned a verification URI with embedded credentials","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/config/src/device_code.rs","lineNumber":199,"sourceCode":"///\n/// Ported from pi's `validateVerificationUri`\n/// (`packages/ai/src/auth/oauth/xai.ts`, MIT, Copyright (c) 2025 Mario\n/// Zechner): the URI comes straight off the wire and is passed to the platform\n/// \"open this\" call, so a malicious or compromised response could otherwise\n/// launch `file:`, a custom app scheme, or a helper with attacker-chosen\n/// arguments. pi requires `https:`; Codewhale additionally allows `http:` on a\n/// loopback host, which is what self-hosted issuers and the device-code tests\n/// use — matching the loopback allowance the account login already makes.\n///\n/// Embedded credentials are rejected in every case.\npub fn validate_browser_verification_uri(raw: &str, context: &str) -> Result<String> {\n    let trimmed = raw.trim();\n    let Ok(url) = url_scheme_and_host(trimmed) else {\n        bail!(\"{context} returned an unusable verification URI\");\n    };\n    let (scheme, host, has_credentials) = url;\n    if has_credentials {\n        bail!(\"{context} returned a verification URI with embedded credentials\");\n    }\n    let allowed = scheme == \"https\" || (scheme == \"http\" && is_loopback_host(&host));\n    if !allowed {\n        bail!(\"{context} returned an untrusted verification URI\");\n    }\n    Ok(trimmed.to_string())\n}\n\n/// Minimal scheme/host/credential split, so this module stays free of a URL\n/// dependency (`codewhale-config` deliberately has no `reqwest`/`url`).\npub(crate) fn url_scheme_and_host(raw: &str) -> Result<(String, String, bool), ()> {\n    let (scheme, rest) = raw.split_once(\"://\").ok_or(())?;\n    if scheme.is_empty()\n        || !scheme\n            .bytes()\n            .all(|b| b.is_ascii_alphanumeric() || b == b'+' || b == b'-' || b == b'.')\n    {\n        return Err(());","sourceCodeStart":181,"sourceCodeEnd":217,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/config/src/device_code.rs#L181-L217","documentation":"Thrown when a device-code verification URI contains embedded credentials (user:password@ in the URL). Credentials in a URI leak secrets into logs, browser history, and referrer headers, so the login flow rejects them unconditionally — even for otherwise-allowed https or loopback hosts.","triggerScenarios":"Calling validate_browser_verification_uri with a URI like https://user:pass@example.com/activate; a provider constructing its verification_uri from a URL that includes basic-auth credentials.","commonSituations":"Reverse-proxy setups where the auth server builds links from an authenticated upstream URL; misconfigured providers that bake service credentials into callback URLs.","solutions":["Remove the user:password@ portion from the verification URI the provider returns","Configure the auth server to issue credential-free public verification URLs","Use headers or a token exchange for authentication instead of URL basic-auth","Point the provider base URL at the public endpoint rather than the credentialed upstream"],"exampleFix":"// before\nlet uri = \"https://user:secret@example.com/activate\";\nvalidate_browser_verification_uri(uri, \"login\")?;\n// after\nlet uri = \"https://example.com/activate\";\nvalidate_browser_verification_uri(uri, \"login\")?;","handlingStrategy":"validation","validationCode":"fn uri_has_credentials(raw: &str) -> bool {\n    raw.trim().split_once(\"://\")\n        .and_then(|(_, rest)| rest.find('@').map(|at| rest[..at].contains(':')))\n        .unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never embed user:password in URLs; use headers for basic auth","Audit proxy/auth-server link generation for credential leakage","Scan logs for credential-bearing URLs"],"tags":["oauth","security","url","credentials"],"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"}