Listening socket mode is left to the umask: group-grant does not work, and umask 0 makes it world-connectable
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
- 45/100
Hướng nghiên cứu
The issue is in the socket binding code across three implementations: go/main.go, rs/src/main.rs, ts/src/index.ts. Start by examining how each creates the AF_UNIX socket and the current umask handling. The fix involves adding flags for socket mode and group, setting umask before bind, and chmod/chown before accept. Testing requires verifying the socket's final permissions and that a client outside the group cannot connect. Look at the systemd fd://3 path to understand when to skip these steps.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Is your feature request related to a problem?
The listening socket's permissions are left entirely to the ambient umask, so the access-control boundary the proxy relies on does not work as documented — and under a permissive umask it does not exist at all.
bind(2) on AF_UNIX creates the inode with 0777 & ~umask. None of the three implementations calls chmod, fchmod, set_permissions or umask around the bind (go/main.go, rs/src/main.rs, ts/src/index.ts). Measured locally:
bind() with umask 022 -> 0o755
bind() with umask 000 -> 0o777
unix(7) states that connecting to a filesystem-visible socket requires write permission on it. Two consequences follow.
1. The documented grant mechanism is inoperative. README.md tells operators to "place the caller's container user in the group that owns the listening socket". At the default umask the socket is 0755 — the group write bit is stripped — so a group member cannot connect(2). Only the owning uid can reach the proxy. The systemd path works, but only because SocketMode=0660 / SocketGroup=builders does the job on systemd's side; the self-bound path, which is the default, silently does not.
2. Fail-open under a permissive umask. If the proxy inherits umask 0 — systemd UMask=0000, a supervisor, an entrypoint that clears it — the socket is 0777 and any local uid with search access to the directory can drive the full Docker API through it.
This was surfaced reviewing #38. It is pre-existing, but that PR raises the stakes: with the TCP listener removed, this file mode becomes the entire access-control boundary rather than one of two paths. Evidence was visible in that PR's own smoke test output and missed: srwxr-xr-x /tmp/dsp-smoke/proxy.sock.
All three implementations behave identically here, so this is not a parity bug. The shared behaviour is simply wrong.
Describe the solution
Take ownership of the socket mode instead of inheriting it:
- Add
--listen-socket-mode(default0660) and--listen-socket-group. - Set
umask(0177)around the bind so the socket is created at0600and is never briefly group- or world-writable, thenchownto the configured group andchmodto the configured mode before the firstaccept(2). - Refuse to start if the resulting mode is world-writable (
o+w) unless an explicit opt-out flag is passed, since that silently disables the boundary. - Skip all of this for
fd://3, where systemd owns the socket andSocketMode/SocketGroupare the right controls. - Cover it: a test asserting the created socket's mode, and an integration case where a client outside the socket's group gets a connection refusal rather than a policy response.
Ordering matters. A plain chmod after bind leaves a window in which the socket is already listening at 0755/0777, so the umask must be set before the bind rather than corrected afterwards.
Describe alternatives
- Document "set your umask" and change nothing. Rejected: it makes the security of the default deployment depend on ambient process state, and the README currently documents a grant mechanism that does not work at the default umask.
- Always hardcode
0660with no flags. Tempting, and much simpler, but it needs a group to be useful — without--listen-socket-groupthe socket is0660 root:rootand no non-root caller can connect. The group option is what makes the mode meaningful. - Bind into a directory whose permissions do the work. Directory
xgrants traversal andwgrants create/unlink, but neither grants the write permissionconnect(2)needs on the socket inode, so this does not substitute for the mode. It is worth doing as well, since write access to the listen directory lets an attacker unlink the live socket and bind their own in its place.
Which implementation(s) would this affect?
- Go
- Rust
- TypeScript
- Quint specification
- All
Additional context
Split out of #38 at review, so the transport change can land without waiting on a new flag surface. #38 has been corrected not to claim a boundary that is not yet enforced.
Related: #39 covers the fact that policy selection has no caller identity. The two together bound what the socket actually gives you — this issue is about who can connect, #39 is about what they can do once connected.
- Ngôn ngữ chính
- Rust
- Star
- 2
- Fork
- 0
- Merge trung bình
- 12 giờ 11 phút
- Pull request đã merge (30 ngày)
- 30
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- 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 ChainSafe/docker-socket-policy
-
Type: Feature
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 12/100
ChainSafe/docker-socket-policy#96 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Priority: P3 Type: Enhancement
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 15/100
ChainSafe/docker-socket-policy#95 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Type: Feature
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 25/100
ChainSafe/docker-socket-policy#65 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Type: Enhancement
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 38/100
ChainSafe/docker-socket-policy#46 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của ChainSafe/docker-socket-policy
Issue tương tự
-
bug documentation sev-0
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
dekobon/big-code-analysis#1620 ·
Maintainer thường phản hồi trong vòng 3 ngày
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
-
bug soroban
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
utilityjnr1/lumena#358 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
enhancement
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
charles-hood/DiagramCraft#63 ·