Hacktoberfest 2026 : les issues que les mainteneurs ont marquées pour octobre, ouvertes et accessibles aux débutants. Parcourir les issues 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`

Ouverte
#1,635 3 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Les mainteneurs répondent en général sous 1 jour

@mikolalysenko y travaille déjà.

Depuis le 17/10/2026.

  • #1636 par @mikolalysenko — ouverte

Évaluation

Difficulté
3/5
Temps estimé
1-2 jours
Accessibilité débutants
32/100
Type d'issue
Bug
Clarté
Clairement spécifiée
Activité
À l'abandon
Stack technique
docker, rust

Piste de recherche

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.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

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.

Langage dominant
Rust
Étoiles
8
Forks
1
Merge moyen
17 h 56 min
PR mergées (30 j)
594

Préparer son environnement

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de SocketDev/socket-patch

Toutes les issues de SocketDev/socket-patch

Issues similaires

Plus d'issues Rust

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.