Repository navigation
Hosted uv scan gives no uv < 0.5.6 advisory for transitive overrides or repointed constraints, so on uv ≤ 0.5.4 a plain uv sync silently reinstalls the unpatched wheel after a clean exit 0 #1569
Description
[agent] Found by the scheduled uv bug-hunt routine (ledger #310).
Summary
When the patched package reaches a uv project transitively, or is named in [tool.uv] constraint-dependencies, the hosted scan wires it through a marked override-dependencies entry plus a [tool.uv.sources] url, or by repointing the lock's [manifest] constraints entry. uv before 0.5.5 doesn't honour either shape:
- A plain
uv syncre-resolves the override or constraint against the registry, rewrites uv.lock and installs the unpatched wheel. uv sync --lockedfails.
Vendored mode handles the same wiring by emitting the advisories pypi_uv_override_requires_uv_0_5_6 and pypi_uv_constraints_require_uv_0_5_6. Hosted mode emits nothing: scan exits 0 with only redirect_pypi_stale_install, so a user on uv ≤ 0.5.4 has no sign that the next plain sync silently drops the patch.
Impact
A silent loss of the security patch on uv 0.2.35–0.5.4, which the hosted uv.lock lane supports. The scan reports success, and nothing in its output tells the user to pin uv ≥ 0.5.5 or make the package a direct dependency, which is the remedy the vendored advisory gives.
Repro (Linux, against a local mock of the patch API serving a patched six 1.16.0)
uv --version # 0.5.3 (0.4.30 and 0.5.4 behave the same)
mkdir demo && cd demo
printf '[project]\nname = "demo"\nversion = "0.1.0"\nrequires-python = ">=3.9"\ndependencies = ["isodate==0.6.1", "attrs==24.2.0"]\n' > pyproject.toml
uv lock -P six==1.16.0 && uv sync
socket-patch scan --mode hosted --yes --json > scan.json # exit 0
grep -o '"[a-z_]*0_5_6"' scan.json # nothing (vendored prints pypi_uv_override_requires_uv_0_5_6)
rm -rf .venv && uv sync --locked # exit 2: "The lockfile at `uv.lock` needs to be updated"
rm -rf .venv && uv sync # exit 0, rewrites uv.lock
.venv/bin/python -c 'import six; print(getattr(six, "SOCKET_PATCHED", 0))' # 0: unpatchedFor the constraint lane, add [tool.uv]\nconstraint-dependencies = ["six==1.16.0"] (or make six a direct dependency that is also constrained). Vendored then warns pypi_uv_constraints_require_uv_0_5_6, and hosted again warns nothing.
Expected vs actual
- Expected: docs/testing/uv-compatibility.md (the "Transitive targets are wired through
[tool.uv] override-dependencies…" bullet, which also describes the hosted ownership mark) says uv applies sources to overrides only from 0.5.6, that a plainuv syncon older releases reinstalls the pristine wheel, and that "the CLI cannot tell those binaries apart from the lock, so the override branch emits the advisory warningpypi_uv_override_requires_uv_0_5_6instead of refusing". The constraints bullet promisespypi_uv_constraints_require_uv_0_5_6in the same way. Hosted should emit the same advisory (or aredirect_*equivalent), since it writes the same shape. - Actual: only vendored emits them. Hosted exits 0 with no advisory.
Matrix (Linux; each cell run twice on fresh directories)
| uv | Lane | Hosted advisory | Vendored advisory | --locked after scan |
Plain uv sync installs |
|---|---|---|---|---|---|
| 0.4.30 | transitive / constraint | none | override / constraints + override | exit 2 | unpatched, lock rewritten |
| 0.5.3 | transitive / constraint | none | yes | exit 2 | unpatched, lock rewritten |
| 0.5.4 | transitive / constraint | none | yes | exit 2 | unpatched, lock rewritten |
| 0.5.5 | transitive / constraint | none | yes | 0 | patched (OK) |
| 0.13.1 | transitive / constraint | none | yes | 0 | patched (OK) |
macOS / Windows: untested (a lock-semantics difference in uv, not an OS one).
First bad
Present on main e76cb9b and on the v5.0.1 release binary. I didn't find any hosted version that emitted the advisory.
Suspect code
- Vendored emits it:
crates/socket-patch-core/src/vendor/pypi_uv.rs:584(override) and:776(constraints). - The hosted override branch has no equivalent:
crates/socket-patch-core/src/utils/python_script.rs:211(if !direct {adds the marked override, and the comment at:645even notes that uv < 0.5.6 ignores sources on overrides). The hosted[manifest] constraintsrepoint is aroundcrates/socket-patch-core/src/utils/python_lock.rs:427.
No probe runs: probe branches are currently blocked for this routine (see ledger #310).
Activity
mikolalysenko commentedon Oct 15, 2026
[agent] Triaged: priority:p1 (uv, PyPI family). Confirmed on main
e76cb9b:pypi_uv_override_requires_uv_0_5_6andpypi_uv_constraints_require_uv_0_5_6are emitted only fromvendor/pypi_uv.rs(lines 584 and 776). No hosted path (utils/python_script.rsoverride branch,utils/python_lock.rs[manifest] constraintsrepoint) emits either advisory or aredirect_*equivalent. Not a duplicate. No open or merged PR addresses it.Generated by Claude Code
mikolalysenko commentedon Oct 16, 2026
[agent] Claiming this issue (shared root cause: the hosted uv override / constraints wiring never emits the uv < 0.5.6 advisories vendored emits). Branch: agent/fix-uv-hosted-old-uv-advisory. Claim-ID: 2026-10-16T12:21:19Z-a7e05a
Generated by Claude Code
mikolalysenko commentedon Oct 16, 2026
[agent] Fix in progress: #1609
Generated by Claude Code
Warn hosted uv users when old uv drops the patch
Test the hosted uv advisories end to end
Cover user-written uv overrides in the advisory
Keep uv advisories out of takeover skip names