[agent] Found by the scheduled uv bug-hunt routine (ledger #310).
Summary
get_global_python_site_packages hard-codes where uv keeps tool environments (uv tool install) and managed interpreters (uv python install). Those hard-coded paths don't match uv's own path resolution:
- Windows, default config: socket-patch scans
%LOCALAPPDATA%\uv\tools, but real uv (0.4.30, 0.5.31, 0.8.17 and 0.9.5 all tested) installs tools under %APPDATA%\uv\tools (C:\Users\runneradmin\AppData\Roaming\uv\tools, per uv tool dir). So no uv tool environment is ever found by scan -g on Windows.
- All OSes:
UV_TOOL_DIR and XDG_DATA_HOME are ignored. socket-patch always scans ~/.local/share/uv/tools, even when uv tool dir reports somewhere else.
- Linux/macOS:
UV_PYTHON_INSTALL_DIR is ignored. Packages installed into a uv-managed interpreter outside ~/.local/share/uv/python are never found. The same interpreter copied under the default dir is found.
scan -g exits 0 with status: success. Nothing tells the user that a whole class of global installs was skipped.
Impact
-g is documented as "Operate on globally-installed packages" (CLI_CONTRACT.md, Global arguments). The crawler explicitly tries to cover uv tool envs and uv-managed Pythons (see the comments at python_crawler.rs:1250 and :1296). Every command that resolves global PyPI paths uses the same get_site_packages_paths path (ecosystem_dispatch.rs:280): scan, get, apply, rollback and vex. A vulnerable dependency inside a uv tool installed CLI is therefore silently never reported, patched or attested on Windows, and likewise on Linux/macOS for anyone who relocates uv's dirs (common in CI, Docker images and dotfile setups).
I could not confirm the knock-on effect on get -g / apply -g / vex -g end to end. The repo's free e2e patch (725a5343-…, pydantic-ai 0.0.36, used by e2e_pypi.rs::test_pypi_global_lifecycle) now returns not_found from the public proxy even in the lane where scan finds the package. That is a separate observation, unrelated to uv.
Repro (Linux, uv 0.8.17, main 2463257)
H=$(mktemp -d); export HOME=$H
uv tool install --with six==1.16.0 pycowsay # default dir
UV_TOOL_DIR=$H/custom-tools UV_TOOL_BIN_DIR=$H/cbin uv tool install --with idna==3.7 pycowsay
XDG_DATA_HOME=$H/xdg uv tool install --with six==1.15.0 pycowsay
UV_PYTHON_INSTALL_DIR=$H/pyinst uv python install 3.12
uv pip install --system --break-system-packages --python $H/pyinst/cpython-3.12*/bin/python3.12 six==1.14.0
# Point SOCKET_PROXY_URL at any HTTP server that logs POST /patch/batch bodies, then:
mkdir $H/outside && cd $H/outside
socket-patch scan -g --ecosystems pypi --json
UV_TOOL_DIR=$H/custom-tools socket-patch scan -g --ecosystems pypi --json
XDG_DATA_HOME=$H/xdg socket-patch scan -g --ecosystems pypi --json
UV_PYTHON_INSTALL_DIR=$H/pyinst socket-patch scan -g --ecosystems pypi --json
In every run the batch query contains six@1.16.0 (the default tool env) and never idna@3.7, six@1.15.0 or six@1.14.0, even with the matching env var set. All runs exit 0. Control: copying the same cpython-3.12.11-linux-x86_64-gnu dir under ~/.local/share/uv/python/ makes six@1.14.0 appear.
Expected vs actual
- Expected:
scan -g covers the tool envs and managed interpreters wherever uv itself puts them. That means following uv's own resolution: UV_TOOL_DIR, else $XDG_DATA_HOME/uv/tools, else ~/.local/share/uv/tools on Unix and %APPDATA%\uv\tools on Windows. Python installs follow the same pattern with UV_PYTHON_INSTALL_DIR. Alternatively, ask uv tool dir / uv python dir when uv is on PATH. The maintainer note on ledger Bug hunt ledger: uv #310 asks for exactly this: "find every globally installed uv package… none missing".
- Actual: fixed paths only, with
%LOCALAPPDATA% on Windows. Packages are silently missing and the scan exits 0.
OS × uv matrix (probe runs below; "found" = the tool env's dependency appears in the batch query)
| OS |
uv |
default tool dir |
UV_TOOL_DIR |
XDG_DATA_HOME |
UV_PYTHON_INSTALL_DIR |
| Linux (sandbox) |
0.8.17 |
found |
missed |
missed |
missed |
| ubuntu-latest |
0.4.30 / 0.5.31 / 0.8.17 / 0.9.5 |
found |
missed |
– |
– |
| macos-latest |
0.4.30 / 0.5.31 / 0.8.17 / 0.9.5 |
found (~/.local/share/uv/tools) |
missed |
– |
– |
| windows-latest |
0.4.30 / 0.5.31 / 0.8.17 / 0.9.5 |
missed (uv tool dir = %APPDATA%\uv\tools) |
missed |
– |
– |
Not bisected. These hard-coded paths predate v5, and this isn't a regression in #277.
Suspect code
crates/socket-patch-core/src/crawlers/python_crawler.rs:1271-1272: Windows tool root %LOCALAPPDATA%\uv\tools. uv uses %APPDATA%\uv\tools.
crates/socket-patch-core/src/crawlers/python_crawler.rs:1281-1288: Unix tool root hard-coded to ~/.local/share/uv/tools. No UV_TOOL_DIR / XDG_DATA_HOME.
crates/socket-patch-core/src/crawlers/python_crawler.rs:1304-1320: managed-Python root hard-coded. No UV_PYTHON_INSTALL_DIR. The Windows %LOCALAPPDATA%\uv\python root is likely wrong for the same reason, but I didn't probe it.
Similar shape to #443 (Bun env-var dirs) and #415 (pipx), which cover other managers.
Probe runs
[agent] Found by the scheduled uv bug-hunt routine (ledger #310).
Summary
get_global_python_site_packageshard-codes where uv keeps tool environments (uv tool install) and managed interpreters (uv python install). Those hard-coded paths don't match uv's own path resolution:%LOCALAPPDATA%\uv\tools, but real uv (0.4.30, 0.5.31, 0.8.17 and 0.9.5 all tested) installs tools under%APPDATA%\uv\tools(C:\Users\runneradmin\AppData\Roaming\uv\tools, peruv tool dir). So no uv tool environment is ever found byscan -gon Windows.UV_TOOL_DIRandXDG_DATA_HOMEare ignored. socket-patch always scans~/.local/share/uv/tools, even whenuv tool dirreports somewhere else.UV_PYTHON_INSTALL_DIRis ignored. Packages installed into a uv-managed interpreter outside~/.local/share/uv/pythonare never found. The same interpreter copied under the default dir is found.scan -gexits 0 withstatus: success. Nothing tells the user that a whole class of global installs was skipped.Impact
-gis documented as "Operate on globally-installed packages" (CLI_CONTRACT.md, Global arguments). The crawler explicitly tries to cover uv tool envs and uv-managed Pythons (see the comments atpython_crawler.rs:1250and:1296). Every command that resolves global PyPI paths uses the sameget_site_packages_pathspath (ecosystem_dispatch.rs:280): scan, get, apply, rollback and vex. A vulnerable dependency inside auv tool installed CLI is therefore silently never reported, patched or attested on Windows, and likewise on Linux/macOS for anyone who relocates uv's dirs (common in CI, Docker images and dotfile setups).I could not confirm the knock-on effect on
get -g/apply -g/vex -gend to end. The repo's free e2e patch (725a5343-…, pydantic-ai 0.0.36, used bye2e_pypi.rs::test_pypi_global_lifecycle) now returnsnot_foundfrom the public proxy even in the lane where scan finds the package. That is a separate observation, unrelated to uv.Repro (Linux, uv 0.8.17, main
2463257)In every run the batch query contains
six@1.16.0(the default tool env) and neveridna@3.7,six@1.15.0orsix@1.14.0, even with the matching env var set. All runs exit 0. Control: copying the samecpython-3.12.11-linux-x86_64-gnudir under~/.local/share/uv/python/makessix@1.14.0appear.Expected vs actual
scan -gcovers the tool envs and managed interpreters wherever uv itself puts them. That means following uv's own resolution:UV_TOOL_DIR, else$XDG_DATA_HOME/uv/tools, else~/.local/share/uv/toolson Unix and%APPDATA%\uv\toolson Windows. Python installs follow the same pattern withUV_PYTHON_INSTALL_DIR. Alternatively, askuv tool dir/uv python dirwhen uv is on PATH. The maintainer note on ledger Bug hunt ledger: uv #310 asks for exactly this: "find every globally installed uv package… none missing".%LOCALAPPDATA%on Windows. Packages are silently missing and the scan exits 0.OS × uv matrix (probe runs below; "found" = the tool env's dependency appears in the batch query)
UV_TOOL_DIRXDG_DATA_HOMEUV_PYTHON_INSTALL_DIR~/.local/share/uv/tools)uv tool dir=%APPDATA%\uv\tools)Not bisected. These hard-coded paths predate v5, and this isn't a regression in #277.
Suspect code
crates/socket-patch-core/src/crawlers/python_crawler.rs:1271-1272: Windows tool root%LOCALAPPDATA%\uv\tools. uv uses%APPDATA%\uv\tools.crates/socket-patch-core/src/crawlers/python_crawler.rs:1281-1288: Unix tool root hard-coded to~/.local/share/uv/tools. NoUV_TOOL_DIR/XDG_DATA_HOME.crates/socket-patch-core/src/crawlers/python_crawler.rs:1304-1320: managed-Python root hard-coded. NoUV_PYTHON_INSTALL_DIR. The Windows%LOCALAPPDATA%\uv\pythonroot is likely wrong for the same reason, but I didn't probe it.Similar shape to #443 (Bun env-var dirs) and #415 (pipx), which cover other managers.
Probe runs
uv tool diroutput is the same)not_found)