jdx/mise · error · eyre::Report
remote cache URL must use HTTPS except for loopback developm
Error message
remote cache URL must use HTTPS except for loopback development servers
What it means
validate_remote_url rejects plain-http base URLs on non-loopback hosts whenever the client is authenticated — i.e. a non-empty token, a token_file, or an oidc_audience is configured. This prevents bearer credentials from crossing the network in cleartext. Unauthenticated plain http to a non-loopback host is allowed but logs a warning that cache traffic can be read or modified in transit.
Source
Thrown at crates/mise-cache-core/src/lib.rs:809
} else {
bail!("GitHub Actions OIDC request URL must use HTTPS")
}
}
fn validate_remote_url(base_url: &Url, authenticated: bool) -> Result<()> {
if base_url.scheme() == "https" {
return Ok(());
}
if base_url.scheme() != "http" {
bail!("remote cache URL must use HTTPS");
}
let is_loopback = base_url.host().is_some_and(|host| match host {
Host::Domain(host) => host.eq_ignore_ascii_case("localhost"),
Host::Ipv4(address) => address.is_loopback(),
Host::Ipv6(address) => address.is_loopback(),
});
if !is_loopback && authenticated {
bail!("remote cache URL must use HTTPS except for loopback development servers");
}
if !is_loopback {
warn!(
"using an unauthenticated remote build cache over plain HTTP; cache traffic can be read \
or modified in transit"
);
}
Ok(())
}
fn normalized_base_url(mut url: Url) -> Url {
if !url.path().ends_with('/') {
url.set_path(&format!("{}/", url.path()));
}
url
}
fn retry_delays(retries: i64) -> impl Iterator<Item = Duration> {View on GitHub (pinned to 9dcfcaa0dc)
Solutions
- Serve the cache over https (add TLS at the server or expose it through an https ingress and give the client that URL)
- For a local dev server, point base_url at a loopback host (localhost, 127.0.0.1, ::1) where http with credentials is accepted
- If the cache is genuinely unauthenticated, remove the token/token_file/oidc_audience so the client is not classified as authenticated (a tampering warning is still logged)
Example fix
# before base_url = "http://cache.corp.internal" token = "secret" # authenticated over plain http -> rejected # after base_url = "https://cache.corp.internal" token = "secret"
Defensive patterns
Strategy: validation
Validate before calling
fn cache_url_allows_auth(url: &url::Url) -> bool {
if url.scheme() == "https" {
return true;
}
if url.scheme() != "http" {
return false;
}
url.host().is_some_and(|h| match h {
url::Host::Domain(h) => h.eq_ignore_ascii_case("localhost"),
url::Host::Ipv4(a) => a.is_loopback(),
url::Host::Ipv6(a) => a.is_loopback(),
_ => false,
})
}
// before building an authenticated RemoteCacheConfig
anyhow::ensure!(
cache_url_allows_auth(&config.base_url),
"refusing to send credentials over plain http to {}",
config.base_url
); Prevention
- Default cache URLs to https in all environments except loopback dev
- Terminate TLS at an ingress the client can reach via its https URL
- Use loopback hosts (localhost/127.0.0.1/::1) for local authenticated dev servers
When it happens
Trigger: Configuring base_url = http://cache.corp.internal together with a token, token file, or OIDC audience; a TLS-terminating load balancer where the client-visible internal URL is http; moving a dev setup from localhost to a LAN host while keeping http and the token.
Common situations: Internal cache servers without TLS certificates; ingress topologies where TLS stops at the edge; CI configuring the token via env while the URL was only ever tested on localhost.
Related errors
- GitHub Actions OIDC request URL must use HTTPS
- remote cache URL must use HTTPS
- remote cache path escapes its output root
- unsupported remote cache digest algorithm
- invalid remote cache digest
AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17).
Data as JSON: /api/errors/ea7264c1545185fc.
Report an issue: GitHub.