With the same release in user site-packages and a system site-packages dir, agent mode patches the shadowed system copy, leaves the copy Python imports unpatched, and VEX attests it (worse since #452: now hits apt-installed packages)
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 58/100
Hướng nghiên cứu
Start with the Linux reproduction, then read crates/socket-patch-core/src/crawlers/python_crawler.rs:1316 and the well-known-directory scan, followed by crates/socket-patch-cli/src/commands/apply.rs:1861 and :1888-1898. Verify behavior with the scan, apply, vex, and rollback commands from the report. Done means the interpreter-loaded copy is patched, duplicate installs are handled consistently, and VEX does not attest an unpatched loaded copy.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
[agent] Found by the scheduled Poetry bug-hunt routine (ledger #311).
Summary
When one PyPI release (here six==1.16.0) is installed both in the user site (~/.local/lib/python3.X/site-packages, from pip install --user) and in a system site dir (/usr/lib/python3/dist-packages from apt, or /usr/local/lib/python3.X/dist-packages from pip), every global-scope agent run patches the system copy only:
scan -g --mode agent, and- a plain project
scan --mode agentin a Poetry project withvirtualenvs.create = false(or any layout where the project venv isn't found and the crawler falls back to the global interpreter, e.g. #476).
Python imports the user-site copy, because sys.path puts user site before the system dirs. That copy stays unpatched. The run reports success, apply re-runs say already_patched, and vex attests not_affected / inline_mitigations_already_exist. On Debian/Ubuntu the write also lands in a dpkg-owned file (/usr/lib/python3/dist-packages/six.py).
Root cause, two parts:
get_global_python_site_packagesorders paths assite.getsitepackages()first andsite.getusersitepackages()last (crates/socket-patch-core/src/crawlers/python_crawler.rs:1316, plus the well-known-dir scan after it, which also adds~/.locallast). That's the reverse of Python's import precedence.- Apply keeps PyPI on a "one representative" contract and patches only
pkg_paths.first()(crates/socket-patch-cli/src/commands/apply.rs:1861and:1888-1898). The comment there assumes "their crawlers resolve one install dir per version", which doesn't hold in global scope.rollbackdoes fan out to every copy (it reportsrolledBack: 1, alreadyOriginal: 1), so the two commands disagree on how many copies exist.
#452 (2035cbb) made this much easier to hit. Before it, apt's .egg-info installs were invisible, so with apt six plus a user-site six the user copy was the only candidate and got patched correctly. Since #452 the apt copy is listed first and wins. With two dist-info copies (/usr/local/.../dist-packages plus user site), the bug already exists in v4.0.0.
Impact
- A false VEX attestation. The imported copy is still vulnerable, and nothing warns.
- On Debian/Ubuntu (apt ships
six,requests,urllib3,idna,certifi, … as egg-info),-gwrites into dpkg-owned files while leaving the copy actually in use unpatched. - Poetry users with
virtualenvs.create = false(common in Docker images and CI) get the same result from a plain projectscan.
Repro (Linux, Debian bookworm image, Python 3.11, Poetry 2.5.1)
The mock patch API serves one agent patch for pkg:pypi/[email protected] that appends SOCKET_PATCHED = 1 to six.py. It uses the same routes as tests/vex_pypi_real_common/mod.rs, plus /patches/blob/<hash>. $A = --api-url http://127.0.0.1:18080 --api-token fake --org test-org --patch-server-url http://127.0.0.1:18080.
# apt's python3-six 1.16.0 egg-info is in /usr/lib/python3/dist-packages
python3 -m pip install --user --ignore-installed --break-system-packages six==1.16.0
python3 -c 'import six; print(six.__file__)' # -> /root/.local/lib/python3.11/site-packages/six.py
mkdir nc && cd nc
cat > pyproject.toml <<'EOF'
[tool.poetry]
name = "demo"
version = "0.1.0"
description = ""
authors = ["x <x@x>"]
package-mode = false
[tool.poetry.dependencies]
python = "^3.11"
six = "1.16.0"
EOF
printf '[virtualenvs]\ncreate = false\n' > poetry.toml
poetry lock && poetry install # "No dependencies to install or update"
poetry run python -c 'import six; print(six.__file__)' # user-site copy
socket-patch scan --mode agent --yes $A # success (same with: mkdir g && cd g && socket-patch scan -g --mode agent --yes $A)
grep -c SOCKET_PATCHED /usr/lib/python3/dist-packages/six.py # 1 <- shadowed copy patched
grep -c SOCKET_PATCHED ~/.local/lib/python3.11/site-packages/six.py # 0 <- imported copy unpatched
python3 -c 'import six; print(hasattr(six, "SOCKET_PATCHED"))' # False
socket-patch apply --json $A # skipped / already_patched
socket-patch vex --product pkg:pypi/[email protected] --json --output v.json $A # not_affected / inline_mitigations_already_exist
socket-patch rollback --json $A # rolledBack: 1, alreadyOriginal: 1 (it sees both copies)
It reproduces 2/2 for each of: scan -g --mode agent, vex -g, and the Poetry create = false project scan.
Expected vs actual
- Expected: agent mode patches the copy the interpreter loads, or every installed copy as gem/npm do (
apply.rscomment: "leaving the other store pristine is a silent false 'applied'"). VEX only attests when the loaded copy is patched. CLI_CONTRACT.md's VEX rule is that a statement is emitted only for a patch that is actually applied. - Actual: the shadowed copy is patched, the loaded copy isn't, and VEX attests anyway.
OS × version
| OS | Copies present | Binary | Result |
|---|---|---|---|
| Linux | apt egg-info + user site | main 61cfb9b, 2035cbb (#452) |
fail: apt copy patched |
| Linux | apt egg-info + user site | v4.0.0, 2035cbb^ | pass: user copy patched |
| Linux | /usr/local/.../dist-packages dist-info + user site |
main, 2035cbb^, v4.0.0 | fail: /usr/local copy patched |
| Linux | /usr/local/.../dist-packages only |
main | pass |
| macOS / Windows | — | — | untested (probe branches blocked). macOS user site (~/Library/Python/3.X/lib/python/site-packages) has the same ordering, so it's likely affected. |
Poetry versions: 2.5.1 (create = false, user-site copy kept). With create = false, Poetry 1.8.5 / 2.0.1 / 2.2.1 in this image reinstalled six into /usr/local/lib/python3.11/dist-packages, which precedes apt on sys.path, so those didn't reproduce until a user-site copy was re-added. The -g path doesn't depend on the Poetry version.
First bad commit
For the apt + user-site case: 2035cbb ("Fix Python crawler missing .egg-info installs (#447) (#452)"), bisected with release builds of 2035cbb^ and 2035cbb, 2/2 each. For two dist-info copies, it never worked (v4.0.0 fails).
Suspect code
crates/socket-patch-core/src/crawlers/python_crawler.rs:1316(user site printed last) and the well-known-dir order right after it.crates/socket-patch-cli/src/commands/apply.rs:1861,:1888-1898(PyPI patches onlypkg_paths.first()).- Related but distinct: #409 (
--system-site-packagesvenv, hosted), #476 (Poetry venv not found, so this fallback is reached).
- Ngôn ngữ chính
- Rust
- Star
- 8
- Fork
- 0
- Merge trung bình
- 1 ngày 1 giờ
- Pull request đã merge (30 ngày)
- 257
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Không có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của SocketDev/socket-patch
-
agent:triaged bug bughunt pm:npm priority:p1
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
SocketDev/socket-patch#1127 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
agent:triaged bug bughunt pm:bundler priority:p1
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
SocketDev/socket-patch#1125 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
agent:triaged bug bughunt pm:pipenv priority:p1
Độ khó 2/5 Dưới một giờ Mức phù hợp với người mới 85/100
SocketDev/socket-patch#1122 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
agent:triaged bug bughunt pm:npm priority:p1
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
SocketDev/socket-patch#1072 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
agent:triaged arch-audit bug priority:p3
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
SocketDev/socket-patch#1062 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của SocketDev/socket-patch
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
-
documentation enhancement
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 62/100
adorsys/status-list-server#619 ·
Maintainer thường phản hồi trong vòng 2 ngày
-
batch-backport only backports the first 30 matching PRsCó thể đã có người làm @DvirDukhan đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
Maintainer thường phản hồi trong vòng 5 ngày
-
Configuration-level resource: `Allocate` rejects the kubelet's re-offer of the same device for a later container of the same Pod ("Unable to claim slot")Có thể đã có người làm @fang80913 đã nhận 38 ngày trước. Đang mởbug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
project-akri/akri#854 ·
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 77/100
Maintainer thường phản hồi trong vòng 1 ngày