Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

Hosted and vendored rewrites replace poetry.lock with a file owned by the user running socket-patch, so after a root scan (e.g. a Docker bind mount) the lock's owner gets "Permission denied" from `poetry add` / `poetry lock`

Đang mở
#1,635 3 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

@mikolalysenko đang làm issue này rồi.

Từ ngày 17/10/2026.

  • #1636 của @mikolalysenko — đang mở

Đá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
32/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Đình trệ
Công nghệ
docker, rust
Lĩnh vực
cli, operating-systems, tooling

Hướng nghiên cứu

Start with crates/{{USERNAME_vczr4cqb31}}-core/src/utils/fs.rs, especially stage_and_rename_blocking, and compare it with restore_file_permissions. Trace the Poetry callers in vendor/pypi_poetry.rs and patch/redirect/staged.rs; add or identify tests that verify uid/gid preservation for host-owned files after staged rewrites. Done means hosted, vendored, and rollback lockfile rewrites preserve ownership where permitted, with relevant platform-specific tests passing.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

agent:claimed agent:triaged bug bughunt pm:poetry priority:p1

[agent] Found by the scheduled Poetry bug-hunt routine (ledger #311).

Summary

Hosted and vendored lock rewrites (and rollback / vendor --revert) write poetry.lock by staging a new file and renaming it over the old one (atomic_write_bytes_preserving_mode). The stage keeps the old file's permission bits but not its owner or group, so the rewritten poetry.lock belongs to whoever ran socket-patch.

  • Run as root on a project owned by a normal user (the usual docker run -v "$PWD:/app" … socket-patch scan setup, or sudo): poetry.lock turns into root:root 0644. Its real owner can still read it, but every Poetry command that writes the lock (poetry add, poetry lock, poetry remove, poetry update) then fails with [Errno 13] Permission denied: '…/poetry.lock'. Poetry writes the lock in place, so it can't replace a root-owned file. (Running git checkout poetry.lock or another socket-patch run as the user does work, because those replace the directory entry.)
  • Run as a normal user in a shared checkout whose files belong to a team group (ubuntu:devs 0664, directory not setgid): the lock is reassigned to the user's primary group (ubuntu:ubuntu 0664), so the other devs members lose write access to it.

Control: Poetry itself running as root (poetry add --lock idna==3.7) rewrites the same lock and keeps it owned by 1000:1000. Afterwards the owner's poetry add works.

The patch engine already restores uid/gid for files it patches (restore_file_permissions, mentioned in the doc comment at crates/socket-patch-core/src/utils/fs.rs:440). The lockfile writer doesn't.

Impact

After a containerised or sudo run, the next dependency change by the project's owner fails until they chown the lock back. Nothing tells them socket-patch changed the owner. pyproject.toml (which hosted and vendored don't write) keeps its owner, so the failure looks like a broken lock rather than a permissions change.

Repro (Linux, real Poetry 2.5.1; same with 1.8.5)

# as root; uid 1000 = ubuntu
mkdir /srv/own && cd /srv/own
cat > pyproject.toml <<'EOF'
[tool.poetry]
name = "demo"
version = "0.1.0"
description = ""
authors = ["x <[email protected]>"]
[tool.poetry.dependencies]
python = "^3.8"
six = "1.16.0"
EOF
poetry lock && chown -R 1000:1000 /srv/own
stat -c '%u:%g %a' poetry.lock          # 1000:1000 644
socket-patch scan --mode hosted --yes   # or --mode vendored; a patch for [email protected]
stat -c '%u:%g %a' poetry.lock          # 0:0 644
su ubuntu -c 'cd /srv/own && poetry add --lock attrs==23.2.0'
# [Errno 13] Permission denied: '/srv/own/poetry.lock'   (exit 1)
socket-patch rollback --yes; stat -c '%u:%g' poetry.lock   # still 0:0

The patch data came from a local mock of the patch API serving a patched copy of the real six-1.16.0 wheel (patches-api.socket.dev is unreachable from the sandbox). The repo's vex_pypi_real_common mock has the same shape. Ownership doesn't depend on the patch content.

Expected vs actual

  • Expected: an edit to a file the user owns keeps its owner and group, the same as its mode. The doc comment on atomic_write_bytes_preserving_mode says it's for "files the user owns and we merely edit … matching npm's write-file-atomic", and write-file-atomic also chowns the new file to the old file's uid/gid when it can. crates/socket-patch-cli/CLI_CONTRACT.md says nothing about ownership; it only promises that a rewrite's stage keeps the old permission bits.
  • Actual: the replacement file is owned by the euid/egid of the socket-patch process.

Matrix

OS Poetry Mode Run as Result
Linux 2.5.1 hosted scan root fail (0:0, owner's poetry add --lock exit 1), 2/2
Linux 2.5.1 vendored scan root fail (same)
Linux 1.8.5 vendored scan, then root rollback root fail (0:0 after both, owner's poetry add --lock exit 1)
Linux 2.5.1 hosted scan non-root member of the file's group fail (ubuntu:devs → ubuntu:ubuntu)
Linux 2.5.1 control: poetry add --lock root pass (stays 1000:1000)
macOS / Windows – – – untested (no probe branch this run; Windows has no POSIX owner, and macOS behaves like Linux for rename)

Release v5.0.1 (npm @socketsecurity/socket-patch) behaves the same as main 7d3086f, so this isn't a recent regression.

Suspect code

  • crates/socket-patch-core/src/utils/fs.rs:735 (stage_and_rename_blocking): only metadata(path).permissions() is carried over to the stage (set_permissions at ~:752). There's no fchown to the old uid/gid before the rename. A best-effort std::os::unix::fs::fchown(&file, Some(uid), Some(gid)) (ignoring EPERM, as write-file-atomic does) would fix it.
  • Callers that write poetry.lock: crates/socket-patch-core/src/vendor/pypi_poetry.rs:399, crates/socket-patch-core/src/patch/redirect/staged.rs:60 / :88, crates/socket-patch-cli/src/commands/scan/hosted.rs:2079 / :2133, crates/socket-patch-cli/src/commands/vendor.rs:270 / :1676.

This writer is shared, so every ecosystem's lockfile and manifest rewrite (package.json, .npmrc, Gemfile.lock, …) probably behaves the same way. I've only verified the Poetry path.

Ngôn ngữ chính
Rust
Star
8
Fork
1
Merge trung bình
16 giờ 39 phút
Pull request đã merge (30 ngày)
584

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. 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.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của SocketDev/socket-patch

Tất cả issue của SocketDev/socket-patch

Issue tương tự

Thêm issue về Rust

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.