{"record":{"id":"07283582b98ab450","repo":"jdx/mise","slug":"github-actions-oidc-request-url-must-use-https","errorCode":null,"errorMessage":"GitHub Actions OIDC request URL must use HTTPS","messagePattern":"GitHub Actions OIDC request URL must use HTTPS","errorType":"validation","errorClass":"eyre::Report","httpStatus":null,"severity":"error","filePath":"crates/mise-cache-core/src/lib.rs","lineNumber":792,"sourceCode":"fn unix_timestamp() -> Result<u64> {\n    Ok(SystemTime::now()\n        .duration_since(UNIX_EPOCH)\n        .map_err(|err| eyre!(\"system clock is before the Unix epoch: {err}\"))?\n        .as_secs())\n}\n\nfn validate_oidc_request_url(url: &Url) -> Result<()> {\n    if url.scheme() == \"https\"\n        || url.scheme() == \"http\"\n            && url.host().is_some_and(|host| match host {\n                Host::Domain(host) => host.eq_ignore_ascii_case(\"localhost\"),\n                Host::Ipv4(address) => address.is_loopback(),\n                Host::Ipv6(address) => address.is_loopback(),\n            })\n    {\n        Ok(())\n    } else {\n        bail!(\"GitHub Actions OIDC request URL must use HTTPS\")\n    }\n}\n\nfn validate_remote_url(base_url: &Url, authenticated: bool) -> Result<()> {\n    if base_url.scheme() == \"https\" {\n        return Ok(());\n    }\n    if base_url.scheme() != \"http\" {\n        bail!(\"remote cache URL must use HTTPS\");\n    }\n    let is_loopback = base_url.host().is_some_and(|host| match host {\n        Host::Domain(host) => host.eq_ignore_ascii_case(\"localhost\"),\n        Host::Ipv4(address) => address.is_loopback(),\n        Host::Ipv6(address) => address.is_loopback(),\n    });\n    if !is_loopback && authenticated {\n        bail!(\"remote cache URL must use HTTPS except for loopback development servers\");\n    }","sourceCodeStart":774,"sourceCodeEnd":810,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/crates/mise-cache-core/src/lib.rs#L774-L810","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before\nACTIONS_ID_TOKEN_REQUEST_URL=http://oidc.internal:9990/token\n\n# after (real CI: unset the override and use GitHub's injected value)\nunset ACTIONS_ID_TOKEN_REQUEST_URL\n\n# after (local mock: keep it loopback)\nACTIONS_ID_TOKEN_REQUEST_URL=http://127.0.0.1:9990/token","handlingStrategy":"validation","validationCode":"fn oidc_url_is_acceptable(url: &url::Url) -> bool {\n    let loopback = url.host().is_some_and(|h| match h {\n        url::Host::Domain(h) => h.eq_ignore_ascii_case(\"localhost\"),\n        url::Host::Ipv4(a) => a.is_loopback(),\n        url::Host::Ipv6(a) => a.is_loopback(),\n        _ => false,\n    });\n    url.scheme() == \"https\" || (url.scheme() == \"http\" && loopback)\n}\n\n// check before constructing the client with an oidc_audience set\nlet url: url::Url = std::env::var(\"ACTIONS_ID_TOKEN_REQUEST_URL\")?.parse()?;\nanyhow::ensure!(oidc_url_is_acceptable(&url), \"OIDC URL must be https (or loopback http)\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["oidc","https","url-validation","github-actions","security"],"backgroundTag":"https-url-required","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}