{"record":{"id":"de2fb8323cead3ff","repo":"Hmbown/CodeWhale","slug":"remote-url-must-not-embed-userinfo","errorCode":null,"errorMessage":"remote url must not embed userinfo","messagePattern":"remote url must not embed userinfo","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/cloud_dispatch.rs","lineNumber":417,"sourceCode":"pub fn safe_git_remote_url(raw: &str) -> bool {\n    validate_git_remote_url(raw).is_ok()\n}\n\n/// Classify and validate `job.remote_url` before any `git clone` or\n/// sandbox clone. Returns the trimmed URL on success.\npub fn validate_git_remote_url(raw: &str) -> Result<String> {\n    let url = raw.trim();\n    if url.is_empty() || url.len() > MAX_REMOTE_BYTES {\n        bail!(\"remote url is empty or oversized\");\n    }\n    if url.starts_with('-') {\n        bail!(\"remote url must not start with '-'\");\n    }\n    if url.chars().any(char::is_control) {\n        bail!(\"remote url contains control characters\");\n    }\n    if remote_has_userinfo(url) {\n        bail!(\"remote url must not embed userinfo\");\n    }\n    if looks_like_network_git_url(url) && classify_url(url).is_none() {\n        bail!(\"remote url is not a supported forge\");\n    }\n    Ok(url.to_string())\n}\n\n/// Display form of a remote: userinfo is never printed.\npub fn redact_remote_url(raw: &str) -> String {\n    redact_url_userinfo(raw)\n}\n\nfn remote_has_userinfo(url: &str) -> bool {\n    if let Ok(parsed) = reqwest::Url::parse(url) {\n        return !parsed.username().is_empty() || parsed.password().is_some();\n    }\n    // scp-style `user:token@host:path` (plain `git@host:path` is identity, not a secret).\n    if let Some((userinfo, _host)) = url.split_once('@') {","sourceCodeStart":399,"sourceCodeEnd":435,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/cloud_dispatch.rs#L399-L435","documentation":"validate_git_remote_url refuses URLs that embed userinfo (remote_has_userinfo), i.e. credentials in the form scheme://user:pass@host. Embedding secrets in remote URLs leaks them into git config, logs, and process listings, so this form is banned outright.","triggerScenarios":"Calling validate_git_remote_url / safe_git_remote_url / clone_repository with a URL containing an `user:password@` (or `token@`) component before the host — commonly an HTTPS URL with a PAT baked in, or an SSH URL with an explicit user plus secret-looking segment detected by the helper.","commonSituations":"Copy-pasting an authenticated clone URL from a CI secret or a token-scoped URL provided by a forge; storing a PAT inside the remote to 'make it work'; a template that interpolates credentials into the URL.","solutions":["Remove the userinfo and use the plain https://host/org/repo.git form; supply credentials via the git credential helper or environment instead.","Regenerate/revoke any token that was embedded in the URL — it should be considered leaked.","Use SSH remotes (git@github.com:org/repo.git) with key auth rather than token-in-URL.","Redact before displaying: redact_remote_url exists for the display path; never print the raw URL."],"exampleFix":"// before\nlet url = \"https://ghp_SECRET@github.com/org/repo.git\";\nvalidate_git_remote_url(url)?;\n// after\nlet url = \"https://github.com/org/repo.git\"; // auth via credential helper\nvalidate_git_remote_url(url)?;","handlingStrategy":"validation","validationCode":"fn embeds_userinfo(url: &str) -> bool {\n    // crude check: credentials before host in an authority component\n    url.contains('@') && !url.starts_with(\"git@\")\n}","typeGuard":null,"tryCatchPattern":"match validate_git_remote_url(raw) {\n    Err(e) if e.to_string().contains(\"userinfo\") => {\n        eprintln!(\"remove embedded credentials; use a credential helper instead\");\n        eprintln!(\"display form: {}\", redact_remote_url(raw));\n    }\n    other => { /* ... */ }\n}","preventionTips":["Never interpolate tokens/passwords into remote URLs; use git credential helpers.","Revoke and rotate any credential that has appeared in a URL.","Always display remotes via redact_remote_url, never raw.","Scan configs/repos for ':.*@' patterns in URLs in CI."],"tags":["security","git","credentials","url"],"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-23T08:17:48.524Z"}