jdx/mise · error

unsupported query parameter

Error message

unsupported query parameter

What it means

For non-git relayed requests, `authorize` parses the query string and permits only the parameters `ref`, `page`, and `per_page`. Any other query key (sort, client_id, token, callback, etc.) is rejected with this error, keeping the forwarded URL deterministic and preventing credential leakage or cache-busting tricks.

Source

Thrown at src/github_relay.rs:234

            matches!(*kind, "refs" | "matching-refs") && matches!(method, "GET" | "HEAD")
        }
        ["api", "repos", _, _, kind, ..] => {
            matches!(
                *kind,
                "contents" | "releases" | "tags" | "branches" | "tarball" | "zipball"
            ) && matches!(method, "GET" | "HEAD")
        }
        ["web", _, _, "releases", "download", _, ..] => matches!(method, "GET" | "HEAD"),
        ["web", _, _, "archive", _, ..] => matches!(method, "GET" | "HEAD"),
        _ => false,
    };
    if !allowed {
        bail!("GitHub relay permits read-only repository operations only");
    }
    if !git && let Some(query) = query {
        for (key, _) in url::form_urlencoded::parse(query.as_bytes()) {
            if !matches!(key.as_ref(), "ref" | "page" | "per_page") {
                bail!("unsupported query parameter");
            }
        }
    }
    let host = if p[0] == "api" {
        "api.github.com"
    } else {
        "github.com"
    };
    let suffix = path.split_once('/').expect("validated path").1;
    let mut url = format!("https://{host}/{suffix}");
    let archive_repo = match p.as_slice() {
        ["api", "repos", _, _, "tarball" | "zipball", ..] => Some(name.clone()),
        ["web", _, _, "archive", rest @ ..] => {
            let reference = rest.join("/");
            let (kind, reference) = if let Some(reference) = reference.strip_suffix(".tar.gz") {
                ("tarball", reference)
            } else if let Some(reference) = reference.strip_suffix(".zip") {
                ("zipball", reference)

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Strip all query parameters except `ref`, `page`, and `per_page` before forwarding.
  2. Move needed values into the path (e.g. put the ref in the tarball path) instead of the query string.
  3. Authenticate via the relay's own credential handling — never pass `access_token` as a query parameter.

Example fix

// before
relay::forward(&scope, "GET", "/api/repos/o/r/commits", Some("ref=main&sort=dated"))?;
// after
relay::forward(&scope, "GET", "/api/repos/o/r/commits", Some("ref=main"))?;
Defensive patterns

Strategy: validation

Validate before calling

fn relay_safe_query(q: Option<&str>) -> bool {
    q.map(|q| url::form_urlencoded::parse(q.as_bytes())
        .all(|(k, _)| matches!(k.as_ref(), "ref" | "page" | "per_page")))
        .unwrap_or(true)
}

Try / catch

match relay::forward(&scope, "GET", path, Some(query)) {
    Err(e) if e.to_string().contains("query parameter") => eprintln!("strip unsupported query params: {query}"),
    Err(e) => return Err(e),
    Ok(resp) => resp,
}

Prevention

When it happens

Trigger: Calling `forward`/`operation` on an api/web path with a query like `?sort=stars`, `?access_token=...`, `?client_id=`, `?archive_format=zipball`, or an empty-but-present unknown key; git paths are exempt.

Common situations: Clients appending OAuth or analytics params automatically; pagination helpers adding `order`/`sort`; copying an API URL from browser devtools that includes extra params; adding `archive_format` to a tarball URL.

Understand the failure class

Background: "Invalid query parameter" / "Failed to parse value of ...": fixing bad query string parameters across APIs — this error's family across 36 libraries.

Related errors


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