From e8b50375c6e77657b4a2b1dd11dadf20595d3114 Mon Sep 17 00:00:00 2001 From: Zanie Blue Date: Wed, 20 May 2026 16:20:03 -0500 Subject: [PATCH] Ensure that incompatible wheel hints do not leak secrets --- crates/uv-installer/src/plan.rs | 6 +++--- crates/uv/tests/it/pip_sync.rs | 27 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/crates/uv-installer/src/plan.rs b/crates/uv-installer/src/plan.rs index e684a1afae2..d03981a5a54 100644 --- a/crates/uv-installer/src/plan.rs +++ b/crates/uv-installer/src/plan.rs @@ -6,7 +6,6 @@ use anyhow::{Result, bail}; use owo_colors::OwoColorize; use tracing::{debug, warn}; -use url::Url; use uv_cache::{Cache, CacheBucket, WheelCache}; use uv_cache_info::Timestamp; use uv_configuration::{BuildOptions, Reinstall}; @@ -24,6 +23,7 @@ use uv_normalize::PackageName; use uv_platform_tags::{AbiTag, IncompatibleTag, LanguageTag, PlatformTag, TagCompatibility, Tags}; use uv_pypi_types::VerbatimParsedUrl; use uv_python::PythonEnvironment; +use uv_redacted::DisplaySafeUrl; use uv_types::HashStrategy; use crate::satisfies::RequirementSatisfaction; @@ -40,7 +40,7 @@ pub struct IncompatibleWheelError { #[derive(Debug)] enum IncompatibleWheelKind { - Url(Url), + Url(DisplaySafeUrl), Path(PathBuf), } @@ -422,7 +422,7 @@ impl<'a> Planner<'a> { Dist::Built(BuiltDist::DirectUrl(wheel)) => { if !wheel.filename.is_compatible(tags) { return Err(IncompatibleWheelError { - kind: IncompatibleWheelKind::Url(wheel.url.to_url().into()), + kind: IncompatibleWheelKind::Url(wheel.url.to_url()), compatibility_hint: generate_wheel_compatibility_hint( &wheel.filename, tags, diff --git a/crates/uv/tests/it/pip_sync.rs b/crates/uv/tests/it/pip_sync.rs index 1bf94907243..7b3e24c31af 100644 --- a/crates/uv/tests/it/pip_sync.rs +++ b/crates/uv/tests/it/pip_sync.rs @@ -6428,6 +6428,33 @@ fn incompatible_python_version_direct_url() -> Result<()> { Ok(()) } +#[test] +fn incompatible_direct_url_redacts_credentials() -> Result<()> { + let context = uv_test::test_context!("3.12"); + + let requirements_txt = context.temp_dir.child("requirements.txt"); + requirements_txt.write_str("numpy @ https://user:secret@files.pythonhosted.org/packages/ae/11/7c546fcf42145f29b71e4d6f429e96d8d68e5a7ba1830b2e68d7418f0bbd/numpy-2.3.2-cp313-cp313-win32.whl?X-Amz-Signature=signing-secret")?; + + uv_snapshot!(context.filters(), context.pip_sync() + .arg("requirements.txt") + .arg("--python-platform") + .arg("windows"), @" + success: false + exit_code: 2 + ----- stdout ----- + + ----- stderr ----- + Resolved 1 package in [TIME] + error: Failed to determine installation plan + Caused by: A URL (https://user:****@files.pythonhosted.org/packages/ae/11/7c546fcf42145f29b71e4d6f429e96d8d68e5a7ba1830b2e68d7418f0bbd/numpy-2.3.2-cp313-cp313-win32.whl?X-Amz-Signature=****) dependency is incompatible with the current platform + + hint: The wheel is compatible with CPython 3.13 (`cp313`), but you're using CPython 3.12 (`cp312`) + " + ); + + Ok(()) +} + #[test] fn incompatible_platform_direct_url() -> Result<()> { let context = uv_test::test_context!("3.13");