jdx/mise · error

repository origin must not contain credentials, query parame

Error message

repository origin must not contain credentials, query parameters, or fragments

What it means

mise rejects repository origins that embed credentials (password, or non-ssh username), query strings, or URL fragments. Onboarding transfers the repo via a bundle and later re-sets the origin; embedded secrets or extra URL parts break cloning and risk credential leakage.

Source

Thrown at src/system/remote_repository.rs:71

        && origin.split_once("::").is_some_and(|(prefix, _)| {
            !prefix.is_empty() && !prefix.contains(['/', '\\', '[', ']', '@', ':'])
        })
    {
        bail!("Git remote helpers are not supported for remote onboarding");
    }
    if !explicit_local && origin.contains("://") {
        let url = url::Url::parse(origin).wrap_err("invalid repository URL")?;
        if !matches!(url.scheme(), "https" | "ssh" | "file") {
            bail!("remote bootstrap requires HTTPS, SSH, or a local path");
        }
    }
    if let Ok(url) = url::Url::parse(origin)
        && (url.password().is_some()
            || (url.scheme() != "ssh" && !url.username().is_empty())
            || url.query().is_some()
            || url.fragment().is_some())
    {
        bail!("repository origin must not contain credentials, query parameters, or fragments");
    }
    Ok(())
}

impl Source {
    pub(crate) async fn fetch(origin: String) -> Result<Self> {
        validate_origin(&origin)?;
        let directory = tempfile::tempdir()?;
        let repo = directory.path().join("repo");
        let mut command = Command::new("git");
        crate::git::sanitize_git_command(&mut command);
        // No checkout: source templates and hooks are never evaluated locally.
        command
            .env("GIT_ALLOW_PROTOCOL", "https:ssh:file")
            .args(["-c", &crate::git::github_credential_config("github.com")])
            .args([
                "-c",
                &crate::git::github_credential_config("github.com:443"),

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Remove the username/password from the URL and rely on the local git credential helper
  2. Strip query parameters and fragments from the origin
  3. For private repos over SSH, use an ssh:// URL with no inline credentials

Example fix

// before
let origin = "https://user:ghp_xxx@github.com/owner/repo.git?tab=readme";
// after
let origin = "https://github.com/owner/repo.git";
Defensive patterns

Strategy: validation

Validate before calling

fn origin_clean(origin: &str) -> bool {
    origin.contains("@") == false || origin.starts_with("ssh://") || !origin.contains("://")
        && !origin.contains('?') && !origin.contains('#')
}

Type guard

fn is_credential_free_url(origin: &str) -> bool {
    url::Url::parse(origin).map(|u| {
        u.password().is_none()
            && (u.scheme() == "ssh" || u.username().is_empty())
            && u.query().is_none()
            && u.fragment().is_none()
    }).unwrap_or(false)
}

Prevention

When it happens

Trigger: Calling Source::fetch or install_at with an origin such as https://user:token@github.com/owner/repo?ref=main#frag.

Common situations: Pasting a URL copied from a browser address bar while logged in (contains ?tab=... or #...), or hardcoding a PAT into the remote URL.

Understand the failure class

Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.

Related errors


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/80bf56f97be89a03. Report an issue: GitHub.