Hmbown/CodeWhale · error
remote url must not embed userinfo
Error message
remote url must not embed userinfo
What it means
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.
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.
Example fix
// before let url = "https://ghp_SECRET@github.com/org/repo.git"; validate_git_remote_url(url)?; // after let url = "https://github.com/org/repo.git"; // auth via credential helper validate_git_remote_url(url)?;
Defensive patterns
Strategy: validation
Validate before calling
fn embeds_userinfo(url: &str) -> bool {
// crude check: credentials before host in an authority component
url.contains('@') && !url.starts_with("git@")
} Try / catch
match validate_git_remote_url(raw) {
Err(e) if e.to_string().contains("userinfo") => {
eprintln!("remove embedded credentials; use a credential helper instead");
eprintln!("display form: {}", redact_remote_url(raw));
}
other => { /* ... */ }
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
Related errors
- returned a verification URI with embedded credentials
- MCP HTTP URL must not contain credentials; use configured…
- OIDC discovery returned credentials in
- remote url contains control characters
- reviewed plugin MCP endpoint must not contain user…
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/de2fb8323cead3ff.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/cloud_dispatch.rs:417
pub fn safe_git_remote_url(raw: &str) -> bool {
validate_git_remote_url(raw).is_ok()
}
/// Classify and validate `job.remote_url` before any `git clone` or
/// sandbox clone. Returns the trimmed URL on success.
pub fn validate_git_remote_url(raw: &str) -> Result<String> {
let url = raw.trim();
if url.is_empty() || url.len() > MAX_REMOTE_BYTES {
bail!("remote url is empty or oversized");
}
if url.starts_with('-') {
bail!("remote url must not start with '-'");
}
if url.chars().any(char::is_control) {
bail!("remote url contains control characters");
}
if remote_has_userinfo(url) {
bail!("remote url must not embed userinfo");
}
if looks_like_network_git_url(url) && classify_url(url).is_none() {
bail!("remote url is not a supported forge");
}
Ok(url.to_string())
}
/// Display form of a remote: userinfo is never printed.
pub fn redact_remote_url(raw: &str) -> String {
redact_url_userinfo(raw)
}
fn remote_has_userinfo(url: &str) -> bool {
if let Ok(parsed) = reqwest::Url::parse(url) {
return !parsed.username().is_empty() || parsed.password().is_some();
}
// scp-style `user:token@host:path` (plain `git@host:path` is identity, not a secret).
if let Some((userinfo, _host)) = url.split_once('@') {View on GitHub (pinned to 73e0f67d83)