[agent] Found by the scheduled Hatch bug-hunt routine (ledger #314).
Summary
On a Hatch project whose default environment already exists (the normal state for any developer or warm CI cache), socket-patch scan --mode hosted rewrites six==1.16.0 to six @ <hosted wheel>#sha256=… and reports success with no warnings. But the Hatch environment is never actually patched:
- On the next
hatch run, Hatch notices the dependency hash changed and runs pip install "six @ <url>". pip downloads the wheel, sees six 1.16.0 is already installed, and keeps the installed bytes (it exits 0 and prints nothing).
- Hatch then records the new dependency hash as synced, so later
hatch runs never retry. The env stays unpatched until someone runs hatch env remove / hatch env prune.
- socket-patch has a
redirect_pypi_stale_install check for exactly this situation, but it never sees Hatch's environment. Hatch keeps envs out of tree ($HATCH_DATA_DIR/env/virtual/<project>/<hash>/<env>, or the platform data dir by default), and find_local_venv_site_packages only probes VIRTUAL_ENV, .venv/venv, and the Poetry and Pipenv out-of-tree venvs. The warning fires only when the user happens to scan with VIRTUAL_ENV set to the Hatch env.
socket-patch vex run from the project root emits not_affected for the vulnerability, even though the environment hatch run uses holds the unpatched file. With VIRTUAL_ENV pointing at the Hatch env, the same vex omits it (not_applied), which is correct.
The installer = "uv" flavour is not affected: uv reinstalls the direct-URL wheel. A fresh environment is also fine. The problem is pip-installer Hatch envs that already exist, and that's the default.
Related, same root cause: scan --mode agent on a Hatch project applies 0 patches to the Hatch env (it crawls the PATH interpreter instead) and exits 1 partial_failure. The Poetry siblings of this are #327 and #329.
Impact
- Users are told the dependency is patched, and a VEX attestation claims
not_affected, while hatch run / hatch test / hatch shell keep executing the vulnerable code.
- Nothing prompts the remedy (
hatch env remove <env>, or hatch env prune).
Repro (Linux; macOS and Windows identical, see probe)
Uses a local mock of the patch API (the same shape as crates/socket-patch-cli/tests/vex_pypi_real_common: six 1.16.0 with a SOCKET_PATCHED marker). The full mock and driver are in the probe workflow linked below.
pip install hatch==1.18.1
mkdir app && cd app && mkdir -p src/app && touch src/app/__init__.py
cat > pyproject.toml <<'EOF'
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "app"
version = "0.1.0"
dependencies = ["six==1.16.0"]
[tool.hatch.build.targets.wheel]
packages = ["src/app"]
EOF
hatch env create # six 1.16.0 from PyPI
socket-patch scan --mode hosted --json --yes --api-url $API --api-token x --org test-org --patch-server-url $API --ecosystems pypi
# -> status success, redirected 1, warnings []
hatch run python -c "import six; print(hasattr(six,'SOCKET_PATCHED'))" # False
hatch run python -c "import six; print(hasattr(six,'SOCKET_PATCHED'))" # False (hash now recorded as synced)
socket-patch vex --product pkg:pypi/[email protected] --api-url $API --patch-server-url $API --org test-org --api-token x
# -> 1 statement, status not_affected, "Patched via Socket patch … (redirected)"
VIRTUAL_ENV=$(hatch env find default) socket-patch scan --mode hosted --json --yes …
# -> warnings: [redirect_pypi_stale_install] <- only when the env is named explicitly
hatch env remove default
hatch run python -c "import six; print(hasattr(six,'SOCKET_PATCHED'))" # True
Underlying pip behaviour, inside the Hatch env (pip 26.2.1): pip install "six @ http://…/six-1.16.0-py2.py3-none-any.whl#sha256=…" prints Collecting…/Downloading…, exits 0, and leaves six.py unchanged.
Expected vs actual
- Expected: consistent with the PyPI stale-install contract in README.md ("Socket Patch warns (
redirect_pypi_stale_install …) when a venv still holds the upstream release, with the verified remedy") and with how Poetry and Pipenv out-of-tree venvs are handled in find_local_venv_site_packages. A hosted Hatch scan should find the project's Hatch environments and warn with a Hatch-specific remedy (hatch env remove <env> / hatch env prune, not "reinstall from the rewritten lock", which does nothing here). And vex should not attest not_affected while the Hatch env holds the original bytes.
- Actual:
success, warnings: [], the env stays unpatched indefinitely, and vex attests not_affected.
OS × Hatch version (hosted, pip installer, [project] dependencies)
|
1.7.0 |
1.9.7 |
1.16.5 |
1.18.1 |
| Linux (sandbox + ubuntu-latest) |
repro |
repro |
repro |
repro |
| macOS (macos-latest) |
repro |
repro |
repro |
repro |
| Windows (windows-latest) |
repro |
repro |
repro |
repro |
Also reproduced on Linux with [tool.hatch.envs.default] dependencies (env flavour) on 1.16.5. Does not reproduce with installer = "uv" (1.16.5 and 1.18.1: patched on the next hatch run) or on a fresh environment.
First bad
Present since Hatch support landed in 649d457 (#244). No release ships Hatch support yet (v4.0.0 predates it), so there's nothing to bisect.
Suspect code
crates/socket-patch-core/src/crawlers/python_crawler.rs:273 find_local_venv_site_packages: no Hatch environment discovery (compare the Poetry and Pipenv arms at :297 and :307).
crates/socket-patch-cli/src/commands/scan/hosted/python.rs:57: the stale-install judgment only sees those site-packages. Its generic remedy text (:127) doesn't fit Hatch.
- VEX's installed-basis lookup uses the same discovery, so it falls back to the pin basis.
Probe
https://github.com/SocketDev/socket-patch/actions/runs/36740025279 (ubuntu, macos and windows × Hatch 1.7.0 / 1.9.7 / 1.16.5 / 1.18.1, all reproduce).
[agent] Found by the scheduled Hatch bug-hunt routine (ledger #314).
Summary
On a Hatch project whose default environment already exists (the normal state for any developer or warm CI cache),
socket-patch scan --mode hostedrewritessix==1.16.0tosix @ <hosted wheel>#sha256=…and reportssuccesswith no warnings. But the Hatch environment is never actually patched:hatch run, Hatch notices the dependency hash changed and runspip install "six @ <url>". pip downloads the wheel, seessix 1.16.0is already installed, and keeps the installed bytes (it exits 0 and prints nothing).hatch runs never retry. The env stays unpatched until someone runshatch env remove/hatch env prune.redirect_pypi_stale_installcheck for exactly this situation, but it never sees Hatch's environment. Hatch keeps envs out of tree ($HATCH_DATA_DIR/env/virtual/<project>/<hash>/<env>, or the platform data dir by default), andfind_local_venv_site_packagesonly probesVIRTUAL_ENV,.venv/venv, and the Poetry and Pipenv out-of-tree venvs. The warning fires only when the user happens to scan withVIRTUAL_ENVset to the Hatch env.socket-patch vexrun from the project root emitsnot_affectedfor the vulnerability, even though the environmenthatch runuses holds the unpatched file. WithVIRTUAL_ENVpointing at the Hatch env, the samevexomits it (not_applied), which is correct.The
installer = "uv"flavour is not affected: uv reinstalls the direct-URL wheel. A fresh environment is also fine. The problem is pip-installer Hatch envs that already exist, and that's the default.Related, same root cause:
scan --mode agenton a Hatch project applies 0 patches to the Hatch env (it crawls the PATH interpreter instead) and exits 1partial_failure. The Poetry siblings of this are #327 and #329.Impact
not_affected, whilehatch run/hatch test/hatch shellkeep executing the vulnerable code.hatch env remove <env>, orhatch env prune).Repro (Linux; macOS and Windows identical, see probe)
Uses a local mock of the patch API (the same shape as
crates/socket-patch-cli/tests/vex_pypi_real_common: six 1.16.0 with aSOCKET_PATCHEDmarker). The full mock and driver are in the probe workflow linked below.Underlying pip behaviour, inside the Hatch env (pip 26.2.1):
pip install "six @ http://…/six-1.16.0-py2.py3-none-any.whl#sha256=…"printsCollecting…/Downloading…, exits 0, and leavessix.pyunchanged.Expected vs actual
redirect_pypi_stale_install…) when a venv still holds the upstream release, with the verified remedy") and with how Poetry and Pipenv out-of-tree venvs are handled infind_local_venv_site_packages. A hosted Hatch scan should find the project's Hatch environments and warn with a Hatch-specific remedy (hatch env remove <env>/hatch env prune, not "reinstall from the rewritten lock", which does nothing here). Andvexshould not attestnot_affectedwhile the Hatch env holds the original bytes.success,warnings: [], the env stays unpatched indefinitely, andvexattestsnot_affected.OS × Hatch version (hosted, pip installer,
[project] dependencies)Also reproduced on Linux with
[tool.hatch.envs.default] dependencies(env flavour) on 1.16.5. Does not reproduce withinstaller = "uv"(1.16.5 and 1.18.1: patched on the nexthatch run) or on a fresh environment.First bad
Present since Hatch support landed in 649d457 (#244). No release ships Hatch support yet (v4.0.0 predates it), so there's nothing to bisect.
Suspect code
crates/socket-patch-core/src/crawlers/python_crawler.rs:273find_local_venv_site_packages: no Hatch environment discovery (compare the Poetry and Pipenv arms at :297 and :307).crates/socket-patch-cli/src/commands/scan/hosted/python.rs:57: the stale-install judgment only sees those site-packages. Its generic remedy text (:127) doesn't fit Hatch.Probe
https://github.com/SocketDev/socket-patch/actions/runs/36740025279 (ubuntu, macos and windows × Hatch 1.7.0 / 1.9.7 / 1.16.5 / 1.18.1, all reproduce).