Hmbown/CodeWhale · error
bundle redirects may not change URL scheme
Error message
bundle redirects may not change URL scheme
What it means
validate_bundle_redirect enforces that an HTTP redirect during a bundle fetch does not change the URL scheme (e.g. https → http, or http → https crossing onto the wrong class of host). Scheme changes mid-fetch would let a redirect silently downgrade security (TLS to plaintext) or bypass the loopback-only-http rule, so the fetch is aborted.
Solutions
- Point the bundle URL directly at the final destination so no redirect occurs.
- Configure the server to keep redirects scheme-preserving (https→https, http-loopback→http-loopback).
- Have ops fix the redirect chain so the https location does not downgrade to http.
- Test the redirect chain with `curl -IL <url>` and correct the Location header on the server.
Example fix
// before (server config) # server: redirect https://a/bundle -> http://mirror/bundle // after # redirect https://a/bundle -> https://mirror/bundle (scheme preserved)
Defensive patterns
Strategy: validation
Validate before calling
// Before configuring a bundle URL, check the redirect chain:
// curl -sIL -o /dev/null -w '%{url_effective} %{scheme}\n' <bundle-url>
// Ensure every hop keeps the same scheme. Type guard
fn redirect_is_scheme_preserving(initial: &str, next: &reqwest::Url) -> bool {
next.scheme() == initial
} Prevention
- Point bundle URLs at the final destination to avoid redirects entirely.
- Audit server redirect rules so they never downgrade https to http.
- Periodically run curl -IL against bundle endpoints in CI to detect scheme-changing redirects.
When it happens
Trigger: A bundle server responds with 301/302/307/308 whose Location header targets a different scheme than the originally requested scheme; fetch_bundle validates each hop with validate_bundle_redirect, which also validates the redirect target itself.
Common situations: An https bundle URL that redirects to an http mirror; a load balancer redirecting http→https (fails if the client originally used plain http on a non-loopback target anyway); a CDN rewriting to a different scheme.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- bundle fetch request failed
- bundle redirect is missing a valid Location header
- failed to resolve latest stable release from
- MCP HTTP discovered URL must not contain credentials
- MCP HTTP redirect must not contain credentials
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/60cd62a0c8db76a3.
Report an issue: GitHub.
Appendix: source
Thrown at crates/cli/src/config_bundles.rs:833
if !matches!(url.scheme(), "http" | "https") {
bail!("unsupported bundle URL scheme; use https");
}
if !url.username().is_empty() || url.password().is_some() {
bail!("bundle URLs may not include credentials");
}
let host = url.host_str().context("bundle URL must include a host")?;
match url.scheme() {
"https" => Ok(()),
"http" if is_loopback_bundle_host(host) => Ok(()),
"http" => bail!("plain http is only allowed for loopback hosts; use https"),
_ => unreachable!("scheme was validated above"),
}
}
fn validate_bundle_redirect(initial_scheme: &str, next_url: &reqwest::Url) -> Result<()> {
validate_bundle_url(next_url)?;
if next_url.scheme() != initial_scheme {
bail!("bundle redirects may not change URL scheme");
}
Ok(())
}
fn is_loopback_bundle_host(host: &str) -> bool {
let normalized = host
.strip_prefix('[')
.and_then(|value| value.strip_suffix(']'))
.unwrap_or(host);
normalized.eq_ignore_ascii_case("localhost")
|| normalized.to_ascii_lowercase().ends_with(".localhost")
|| normalized
.parse::<std::net::IpAddr>()
.is_ok_and(|address| address.is_loopback())
}
// ---------------------------------------------------------------------------
// ExportView on GitHub (pinned to 73e0f67d83)