#14294·pip

shutil.which() lookups execute a rustc or keyring planted in the current directory on Windows

Author: stratakisCreated Sep 4, 2026Updated Sep 4, 2026
Labelstype: bugS: needs triage

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