scan --sync / --mode agent never re-applies an already-recorded patch, so after a fresh Hatch env (or any reinstall) it exits 0 with the package unpatched
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ó
- 3/5
- Thời gian dự kiến
- 1-2 ngày
- Mức phù hợp với người mới
- 72/100
Hướng nghiên cứu
Start in crates/socket-patch-cli/src/commands/get.rs at the downloaded > 0 gates around lines 2438 and 2485, then trace how scan --mode agent and --sync call download_and_apply_patches_with. Use the provided Hatch reproduction to verify that a second scan after recreating the environment reapplies the recorded patch and does not report success when application fails. The issue does not name a test file.
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 Hatch bug-hunt routine (ledger #314).
Summary
scan --mode agent and scan --sync only run the nested apply when the run downloaded a new or updated patch record. When every discovered patch is already in .socket/manifest.json, the records come back skipped and apply never runs. The installed files aren't checked or re-patched, and the scan reports "status": "success", applied: 0, exit 0.
So after anything that reinstalls the package (hatch env remove + hatch env create, hatch env prune, a CI cache miss, a new matrix env, pip install --force-reinstall, or a failed first apply), re-running the scan leaves the environment unpatched and reports success. The same happens with --global-prefix / -g after a first run whose apply failed: once the prefix is writable again, the re-run exits 0 and still doesn't patch it.
This isn't Hatch-specific. The gate is in the shared download_and_apply_patches_with. I found it with real Hatch, where recreating envs is routine.
Impact
--sync is documented as the one-shot reconciliation: the help text at crates/socket-patch-cli/src/commands/scan/mod.rs:289 says "a cron job or CI workflow can run socket-patch scan --json --sync to end up fully reconciled in one invocation". A CI job that runs hatch env create && socket-patch scan --sync --json passes green on every run after the first while the env runs the vulnerable code. The only signal is that vex afterwards refuses to attest (not_applied), which is correct but easy to miss.
Repro (Linux, Hatch 1.18.1, mock patch API serving a six 1.16.0 patch)
mkdir rr && cd rr && mkdir app && touch 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 = ["app"]
[tool.hatch.envs.default]
path = ".venv"
EOF
export SOCKET_API_URL=http://127.0.0.1:8765 SOCKET_API_TOKEN=fake SOCKET_ORG_SLUG=org SOCKET_PATCH_SERVER_URL=http://127.0.0.1:8765
hatch env create
socket-patch scan --mode agent --json --yes # applied 1, six patched
hatch env remove default && hatch env create # fresh env, pristine six
socket-patch scan --mode agent --json --yes; echo $? # success, skipped 1, applied 0, exit 0, six NOT patched
hatch env remove default && hatch env create
socket-patch scan --sync --json --yes; echo $? # same: success, skipped 1, exit 0, six NOT patched
socket-patch apply --json # applied 1: the only thing that actually reconciles
Output on 1.18.1 (the 1.7.0 output is identical):
scan --mode agent: success applied 1 skipped 0 exit=0 import_patched=True
-- hatch env remove + create
scan --mode agent: success applied 0 skipped 1 exit=0 import_patched=False
-- hatch env remove + create
scan --sync: success applied 0 skipped 1 exit=0 import_patched=False
Warning: omitting pkg:pypi/[email protected] from VEX: the patched files still hold the original content (not_applied)
Global-prefix variant, without Hatch: pip install --target <prefix> six==1.16.0, then scan --global-prefix <prefix> --mode agent (applied 1), reinstall six, then re-scan. The re-scan gives success, skipped 1, exit 0, unpatched. --sync does the same, and each ran twice. Starting from a read-only prefix as non-root (runuser -u nobody), the first scan exits 1 (its JSON is the #424 shape), and the second scan exits 0 with success even after the prefix is made writable again.
Expected vs actual
- Expected:
scan --mode agentrecords and applies (docs/usage.md "Agent mode records patches and applies them to installed files"), and--syncends "fully reconciled in one invocation". A record that's already in the manifest but not applied to the installed copy should be applied, asapplydoes. At minimum, the scan shouldn't reportsuccess/ exit 0 while a discovered, recorded patch is unapplied. - Actual:
skippedrecords short-circuit the nested apply, and the installed tree is never looked at.
OS × version
| Cell | Result |
|---|---|
Linux, Hatch 1.18.1, .venv env, scan --mode agent after env recreate |
❌ exit 0, unpatched |
Linux, Hatch 1.18.1, scan --sync after env recreate |
❌ exit 0, unpatched |
| Linux, Hatch 1.7.0, both of the above | ❌ |
Linux, --global-prefix (pip --target), after reinstall, agent and --sync |
❌ |
Linux, --global-prefix read-only then writable, non-root |
❌ second run exits 0 |
socket-patch apply in the same states (control) |
✅ re-applies |
vex in the same states (control) |
✅ omits not_applied |
The logic is OS-independent (no path or filesystem handling is involved).
First bad version
Released v4.0.0 (PyPI socket-patch==4.0.0) behaves the same, so this isn't a v5 regression.
Suspect code
crates/socket-patch-cli/src/commands/get.rs:2438:let apply_lock = if !params.save_only && downloaded > 0 {. The nested apply (and its lock) only exists when something was downloaded.crates/socket-patch-cli/src/commands/get.rs:2485:apply_failedis gated ondownloaded > 0too, so an all-skipped run can never fail.
Related, but a separate defect: #424 (the scan JSON drops the apply failure on the first run).
- Ngôn ngữ chính
- Rust
- Star
- 8
- Fork
- 1
- Merge trung bình
- 19 giờ 1 phút
- Pull request đã merge (30 ngày)
- 473
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 pm:go priority:p2
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
SocketDev/socket-patch#1409 · 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:p3 ux
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
SocketDev/socket-patch#1072 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
agent:triaged bug bughunt pm:yarn-berry priority:p1
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 73/100
SocketDev/socket-patch#783 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Vendored cargo warns cargo_multi_version_old_cargo ("declares no rust-version") when the root package inherits rust-version from [workspace.package]Có thể đã có người làm Có pull request liên kết đang mở hoặc đã được merge. Đang mởagent:triaged bug bughunt pm:cargo priority:p2
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 84/100
SocketDev/socket-patch#651 · 3 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
agent:triaged bench perf-regression pm:nuget priority:p3
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 45/100
SocketDev/socket-patch#1425 · 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ự
-
ai-priority/P2 bug db/oracle user-priority/P1
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 67/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
swc-project/swc#12516 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
app bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
-
mls-rs-crypto-awslc: exact aws-lc-rs =1.16.3 pin blocks rustls security updateCó thể đã có người làm @muscariello đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100