jdx/mise · error

repository is outside the approved relay scope

Error message

repository is outside the approved relay scope

What it means

After extracting OWNER/REPO from the relayed path, `authorize` checks the parsed repository name against the relay `Scope`'s approved repository list (`scope.permits`). Requesting a repository that was not approved when the relay scope was created fails with this error, enforcing that the relay only ever talks to allow-listed repos.

Source

Thrown at src/github_relay.rs:206

        {
            bail!("invalid relay path");
        }
    }
    Ok(())
}

#[cfg(any(unix, test))]
fn authorize(scope: &Scope, method: &str, path: &str, query: Option<&str>) -> Result<Target> {
    validate_path(path)?;
    let p: Vec<_> = path.split('/').collect();
    let (owner, repo) = match p.as_slice() {
        ["api", "repos", owner, repo, ..] => (*owner, *repo),
        ["git" | "web", owner, repo, ..] => (*owner, repo.strip_suffix(".git").unwrap_or(repo)),
        _ => bail!("unsupported GitHub operation"),
    };
    let name = repository(&format!("{owner}/{repo}"))?;
    if !scope.permits(&name) {
        bail!("repository is outside the approved relay scope");
    }
    let git = p[0] == "git";
    let allowed = match p.as_slice() {
        ["git", _, _, "info", "refs"] => {
            method == "GET" && query == Some("service=git-upload-pack")
        }
        ["git", _, _, "git-upload-pack"] => method == "POST" && query.is_none(),
        ["api", "repos", _, _] => method == "GET" || method == "HEAD",
        ["api", "repos", _, _, "git", kind, ..] => {
            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"),

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Add the repository to the approved scope when creating the relay (e.g. include it in `from_flags`).
  2. Correct the URL/owner/repo typo so it matches an already-approved repository.
  3. Update the dependency or lockfile reference that points at the unapproved repo.

Example fix

// before
let scope = relay::from_flags("octocat/hello-world")?;
relay::forward(&scope, "GET", "/api/repos/octocat/other-repo", None)?;
// after
let scope = relay::from_flags("octocat/hello-world,octocat/other-repo")?;
relay::forward(&scope, "GET", "/api/repos/octocat/other-repo", None)?;
Defensive patterns

Strategy: validation

Validate before calling

fn repo_in_scope(scope_repo: &str, requested: &str) -> bool {
    requested.to_ascii_lowercase() == scope_repo.to_ascii_lowercase()
}
// or: keep the scope's repo list and check membership before forwarding
assert!(repo_in_scope("octocat/hello-world", "OctoCat/Hello-World"));

Try / catch

match relay::forward(&scope, "GET", path, None) {
    Err(e) if e.to_string().contains("approved relay scope") => eprintln!("repo not in scope: {path}"),
    Err(e) => return Err(e),
    Ok(resp) => resp,
}

Prevention

When it happens

Trigger: Forwarding a request whose owner/repo differs from the scope — e.g. scope created for `octocat/hello-world` but the URL points at `octocat/other-repo`, or a dependency that redirects/fetches from a different org/repo; note names are lowercased before comparison.

Common situations: Tools following redirects or release asset links to other repos; a lockfile pinning a fork or renamed repository; passing `owner/repo` with different casing is fine (lowercased), but a different repo name or a typo is not.

Understand the failure class

Background: "You do not have permission" / 403 Forbidden errors: authenticated but not allowed — causes and fixes across open-source libraries — this error's family across 31 libraries.

Related errors


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