Skip to content

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

Open

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 sync re-resolves the override or constraint against the registry, rewrites uv.lock and installs the unpatched wheel.
  • uv sync --locked fails.

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: unpatched

For 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 plain uv sync on 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 warning pypi_uv_override_requires_uv_0_5_6 instead of refusing". The constraints bullet promises pypi_uv_constraints_require_uv_0_5_6 in the same way. Hosted should emit the same advisory (or a redirect_* 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 :645 even notes that uv < 0.5.6 ignores sources on overrides). The hosted [manifest] constraints repoint is around crates/socket-patch-core/src/utils/python_lock.rs:427.

No probe runs: probe branches are currently blocked for this routine (see ledger #310).

Activity

  1. mikolalysenko commented on Oct 15, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Triaged: priority:p1 (uv, PyPI family). Confirmed on main e76cb9b: pypi_uv_override_requires_uv_0_5_6 and pypi_uv_constraints_require_uv_0_5_6 are emitted only from vendor/pypi_uv.rs (lines 584 and 776). No hosted path (utils/python_script.rs override branch, utils/python_lock.rs [manifest] constraints repoint) emits either advisory or a redirect_* equivalent. Not a duplicate. No open or merged PR addresses it.


    Generated by Claude Code

  2. mikolalysenko commented on Oct 16, 2026

    @mikolalysenko
    CollaboratorAuthor

    [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

  3. mikolalysenko commented on Oct 16, 2026

    @mikolalysenko
    CollaboratorAuthor

    [agent] Fix in progress: #1609


    Generated by Claude Code

  4. added 4 commits that reference this issue on Oct 16, 2026
    e7e0087
    bbf5eea
    6481687
    21f5d28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions