shutil.which() lookups execute a rustc or keyring planted in the current directory on Windows
Description
user_agent() calls shutil.which("rustc") then subprocess.check_output(["rustc","--version"]). On Windows both search the cwd ahead of PATH, so a rustc.exe planted in the invocation directory runs, even for commands that build nothing (pip download, pip install --only-binary=:all:), and its output lands in the User-Agent sent to the index.
network/auth.py has the same pattern for keyring, run via subprocess.run when the keyring module is not importable. Reached only when pip consults keyring (401 from the index, or --keyring-provider subprocess). Both lookups
there are affected: shutil.which(cmd, path=...) still prepends the cwd even when PATH is passed explicitly.
POSIX is not fully unaffected: with "." or an empty entry in PATH, which() returns './rustc' or bare 'rustc' and execvp resolves it the same way. Both execute on Linux.
Fix: discard a match resolving into the cwd, and run the rest by absolute path.
The fix would be to ignore a match that resolves into the cwd and run it by absolute path, or just drop the probe.
Expected behavior
The rustc probe and the keyring lookup should run a binary from the cwd.
pip version
26.3.dev0
Python version
any (behavior is in shutil.which / CreateProcess)
OS
Windows
How to Reproduce
On Windows, open cmd:
mkdir %TEMP%\pip-rustc && cd /d %TEMP%\pip-rustc
r.cs ( echo using System; using System.IO; echo class R { static void Main(string[] a^) { echo File.AppendAllText("ran.txt", "ran: rustc " + string.Join(" ", a^)^); echo Console.WriteLine("rustc 99.99.99 (0000000 2026-09-04)"^); echo } } )
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe /nologo /out:rustc.exe r.cs
python -m pip download --no-index --find-links=. no-such-pkg
type ran.txt
Output
ran: rustc --version
This is the planted binary
Code of Conduct
- I agree to follow the PSF Code of Conduct.
Source: pypa/pip