jdx/mise · error · eyre::Report
GitHub Actions OIDC request URL must use HTTPS
Error message
GitHub Actions OIDC request URL must use HTTPS
What it means
The GitHub Actions OIDC request URL (normally injected via ACTIONS_ID_TOKEN_REQUEST_URL) must use https; plain http is accepted only for loopback hosts (localhost, 127.0.0.1, ::1). validate_oidc_request_url enforces this at credential construction so the ACTIONS_ID_TOKEN_REQUEST_TOKEN bearer value is never sent over an unencrypted channel to a remote host.
Source
Thrown at crates/mise-cache-core/src/lib.rs:792
fn unix_timestamp() -> Result<u64> {
Ok(SystemTime::now()
.duration_since(UNIX_EPOCH)
.map_err(|err| eyre!("system clock is before the Unix epoch: {err}"))?
.as_secs())
}
fn validate_oidc_request_url(url: &Url) -> Result<()> {
if url.scheme() == "https"
|| url.scheme() == "http"
&& 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(),
})
{
Ok(())
} 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");
}View on GitHub (pinned to 9dcfcaa0dc)
Solutions
- In real CI, use the https URL GitHub injects — do not override ACTIONS_ID_TOKEN_REQUEST_URL
- For local mocks, bind the server to a loopback host (localhost/127.0.0.1) so http is accepted, or serve it over https
- Audit entrypoint scripts and proxies for rewriting of the variable
Example fix
# before ACTIONS_ID_TOKEN_REQUEST_URL=http://oidc.internal:9990/token # after (real CI: unset the override and use GitHub's injected value) unset ACTIONS_ID_TOKEN_REQUEST_URL # after (local mock: keep it loopback) ACTIONS_ID_TOKEN_REQUEST_URL=http://127.0.0.1:9990/token
Defensive patterns
Strategy: validation
Validate before calling
fn oidc_url_is_acceptable(url: &url::Url) -> bool {
let loopback = 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,
});
url.scheme() == "https" || (url.scheme() == "http" && loopback)
}
// check before constructing the client with an oidc_audience set
let url: url::Url = std::env::var("ACTIONS_ID_TOKEN_REQUEST_URL")?.parse()?;
anyhow::ensure!(oidc_url_is_acceptable(&url), "OIDC URL must be https (or loopback http)"); Prevention
- Never override ACTIONS_ID_TOKEN_REQUEST_URL in real CI
- Bind local mock OIDC servers to 127.0.0.1 or serve them over https
- Audit runner images and proxies for env rewrites
When it happens
Trigger: Setting ACTIONS_ID_TOKEN_REQUEST_URL to an http:// URL with a non-loopback host; a GithubActionsOidcCredential::new call with such a URL; a proxy or entrypoint script rewriting the injected https URL to http; leaking a dev-mode value into CI.
Common situations: Custom runner images that export the variable to point at a mock OIDC server; local development containers with stale env vars; self-hosted setups trying to reach an internal non-TLS endpoint on another machine.
Related errors
- GitHub Actions OIDC token expires too soon
- remote cache URL must use HTTPS except for loopback developm
- macOS binary signature verification failed (invalid signatur
- {operation} is disabled in safe mode (MISE_SAFE=1) See https
- content-level SLSA verification rejected unsafe archive path
AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17).
Data as JSON: /api/errors/07283582b98ab450.
Report an issue: GitHub.