diff --git a/src/backend/aqua.rs b/src/backend/aqua.rs index 7a65e48c44..27f1473202 100644 --- a/src/backend/aqua.rs +++ b/src/backend/aqua.rs @@ -24,7 +24,7 @@ use crate::{ cache::{CacheManager, CacheManagerBuilder}, }; use crate::{ - backend::{Backend, MISE_BINS_DIR, strict_metadata}, + backend::{Backend, MISE_BINS_DIR, backend_arg_matches_registry_backend, strict_metadata}, config::Config, }; use crate::{file, github, minisign}; @@ -1071,6 +1071,7 @@ impl AquaBackend { &pkg.repo_name, github::API_URL, digest, + backend_arg_matches_registry_backend(&self.ba), ) .await } @@ -1162,6 +1163,7 @@ impl AquaBackend { &pkg.repo_name, signer_workflow.as_deref(), None, + backend_arg_matches_registry_backend(&self.ba), ) .await { diff --git a/src/backend/github.rs b/src/backend/github.rs index 8e7eaaac42..01331730e8 100644 --- a/src/backend/github.rs +++ b/src/backend/github.rs @@ -686,7 +686,11 @@ impl UnifiedGitBackend { if parts.len() == 2 { let (owner, repo_name) = (parts[0], parts[1]); match crate::github::sigstore::detect_attestations( - owner, repo_name, api_url, digest, + owner, + repo_name, + api_url, + digest, + self.use_versions_host_for_github_metadata(), ) .await { @@ -797,6 +801,7 @@ impl UnifiedGitBackend { repo_name, None, Some(api_url), + self.use_versions_host_for_github_metadata(), ) .await { @@ -1845,6 +1850,7 @@ impl UnifiedGitBackend { repo_name, None, // We don't know the expected workflow Some(api_url), + self.use_versions_host_for_github_metadata(), ) .await { diff --git a/src/github/sigstore.rs b/src/github/sigstore.rs index 2b05095c05..82240d1da9 100644 --- a/src/github/sigstore.rs +++ b/src/github/sigstore.rs @@ -66,9 +66,10 @@ pub async fn verify_attestation( repo: &str, expected_workflow: Option<&str>, api_url: Option<&str>, + use_versions_host: bool, ) -> AttestationResult { let mut digest = None; - if use_versions_host_for_attestations(api_url) { + if use_versions_host_for_attestations(api_url, use_versions_host) { let artifact_digest = mise_sigstore::calculate_file_digest(artifact_path).await?; match crate::versions_host::github_attestations( &format!("{owner}/{repo}"), @@ -171,8 +172,9 @@ pub async fn detect_attestations( repo: &str, api_url: &str, digest: &str, + use_versions_host: bool, ) -> Result { - if use_versions_host_for_attestations(Some(api_url)) { + if use_versions_host_for_attestations(Some(api_url), use_versions_host) { match crate::versions_host::github_attestations(&format!("{owner}/{repo}"), digest).await { Ok(Some(attestations)) => { trace!( @@ -198,9 +200,9 @@ pub async fn detect_attestations( Ok(!attestations.is_empty()) } -fn use_versions_host_for_attestations(api_url: Option<&str>) -> bool { +fn use_versions_host_for_attestations(api_url: Option<&str>, use_versions_host: bool) -> bool { let settings = crate::config::Settings::get(); - if settings.prefer_offline() || !settings.use_versions_host { + if !use_versions_host || settings.prefer_offline() || !settings.use_versions_host { return false; } @@ -469,8 +471,23 @@ mod tests { fn test_use_versions_host_for_attestations_respects_setting() { let _settings = SettingsGuard::with_versions_host(None, Some(false)); - assert!(!use_versions_host_for_attestations(Some( - crate::github::API_URL - ))); + assert!(!use_versions_host_for_attestations( + Some(crate::github::API_URL), + true + )); + } + + #[test] + fn test_use_versions_host_for_attestations_respects_registry_gate() { + let _settings = SettingsGuard::with_versions_host(None, Some(true)); + + assert!(!use_versions_host_for_attestations( + Some(crate::github::API_URL), + false + )); + assert!(use_versions_host_for_attestations( + Some(crate::github::API_URL), + true + )); } } diff --git a/src/plugins/core/python.rs b/src/plugins/core/python.rs index c9cf979933..5ecaf76247 100644 --- a/src/plugins/core/python.rs +++ b/src/plugins/core/python.rs @@ -726,6 +726,7 @@ impl PythonPlugin { "python-build-standalone", None, // Accept any workflow from repo None, + true, ) .await { diff --git a/src/plugins/core/ruby.rs b/src/plugins/core/ruby.rs index 9594353afd..9fef5ac426 100644 --- a/src/plugins/core/ruby.rs +++ b/src/plugins/core/ruby.rs @@ -27,6 +27,7 @@ use crate::ui::progress_report::SingleReport; use crate::{file, hash, plugins, timeout}; const RUBY_INDEX_URL: &str = "https://cache.ruby-lang.org/pub/ruby/index.txt"; +const DEFAULT_RUBY_PRECOMPILED_URL: &str = "jdx/ruby"; const ATTESTATION_HELP: &str = "To disable attestation verification, set MISE_RUBY_GITHUB_ATTESTATIONS=false\n\ or add `ruby.github_attestations = false` under [settings] in mise.toml"; @@ -435,6 +436,10 @@ impl RubyPlugin { Some(ProvenanceType::GithubAttestations) } + fn use_versions_host_for_precompiled_attestations(source: &str) -> bool { + source == DEFAULT_RUBY_PRECOMPILED_URL + } + /// Check if precompiled binaries should be tried /// Precompiled if: explicit opt-in (compile=false), or experimental + not opted out /// TODO(2026.8.0): make precompiled the default when compile is unset, remove this debug_assert @@ -845,6 +850,7 @@ impl RubyPlugin { repo, None, // Accept any workflow from repo None, + Self::use_versions_host_for_precompiled_attestations(source), ) .await { @@ -1169,7 +1175,6 @@ mod tests { static TEST_SETTINGS_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(()); const DEFAULT_RUBY_BUILD_REPO: &str = "https://github.com/rbenv/ruby-build.git"; const DEFAULT_RUBY_INSTALL_REPO: &str = "https://github.com/postmodern/ruby-install.git"; - const DEFAULT_RUBY_PRECOMPILED_URL: &str = "jdx/ruby"; struct SettingsResetGuard { _lock: std::sync::MutexGuard<'static, ()>, @@ -1280,6 +1285,16 @@ mod tests { ); } + #[test] + fn test_ruby_precompiled_versions_host_only_for_default_source() { + assert!(RubyPlugin::use_versions_host_for_precompiled_attestations( + DEFAULT_RUBY_PRECOMPILED_URL + )); + assert!(!RubyPlugin::use_versions_host_for_precompiled_attestations( + "acme/ruby" + )); + } + #[test] fn test_ruby_lockfile_options_include_precompiled_inputs() { let opts = resolve_ruby_lockfile_options(|settings| {