From fd2832b6d23dd44c99c66ca75293e8f84d01ff90 Mon Sep 17 00:00:00 2001 From: Dai Ha Date: Thu, 3 Sep 2026 16:44:51 +0700 Subject: [PATCH] Features: state the honest boundary a member runs inside (#184) Several settings on this page look like security controls. They are not, and the reason is the same for all of them: a member runs as the same OS user as the lead. That fact was written nowhere an operator reads, so people read the settings and concluded a member was contained. Adds one entry giving the per-channel truth, the proven path a member takes to the operator's ssh key, and the point that no meaningful boundary exists inside one uid. Names the recurring shape: a gate written after an incident closes only the direction that incident came from. --- 11-Features.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/11-Features.md b/11-Features.md index f935188..0af209c 100644 --- a/11-Features.md +++ b/11-Features.md @@ -3113,6 +3113,44 @@ describes the wrong account and only the configured `memberLoginShell:` is read. `memberHerdrSocket` and leave `memberLoginShell` unset, the shell reads as ``, counts as non-zsh, and **every spawn is refused**. The refusal message says so, but it is cheaper to know first. +## What a member can actually reach — the honest boundary + +**What.** This is not a feature. It is the frame every credential setting on this page sits inside, +and it has been missing, so people have read those settings and concluded more than the settings say. + +**A member runs as the same OS user as the lead. That is a trust model, not a sandbox.** Inside one +uid, ordinary Unix file permissions give no confidentiality boundary. A member that can run commands +can read any file this user can read. + +What each control actually does: + +| Channel | Control today | What it really buys | +|---|---|---| +| Environment | `memberCredentials` + the `ZDOTDIR` scrub | **Real**, for what the member *inherits*. It does not protect the values — the member can source the same files again. | +| Files | worktree provisioning neutralizes some config files | **Not a boundary.** File modes do not separate processes with the same uid. A member can read the original by absolute path. | +| Sockets | `sshAuthSock: block` | **Not a boundary.** It omits one variable. It does not revoke access to the socket, and it cannot remove a readable key file. | +| Git config | the worktree's HTTPS rewrite + cleared `credential.helper` | **Routing, not enforcement.** Normal git commands go the intended way; a member can still call `ssh` directly. | +| Process table | secrets kept out of argv | **No boundary.** argv is visible to any local user, and a different uid would not fix that. | + +**Why it exists.** The proven path is short: the scrub blanks `SSH_AUTH_SOCK` → git starts ssh → ssh +reads the user's config → it opens an `IdentityFile` that is readable and has no passphrase → the +forge accepts the operator's key. Measured on 2026-08-28: a member with the socket blanked pushed +successfully. The gate closes lead → child environment inheritance. It never closed member → +filesystem → credential. + +That is worth naming as a shape, because it keeps recurring here: **a gate written after an incident +closes only the direction that incident came from.** Ask which states open it, not just which it +blocked. + +**The gotcha: no meaningful boundary exists inside one uid.** Environment scrubbing, worktrees and +config rewrites reduce **accidents**, and that is worth having. They do not contain a member that +chooses to look. A real boundary needs a different OS user (`memberHerdrSocket`, above) or OS-level +confinement such as a container or VM — a different execution model, not a longer name list. Even a +different user does not protect argv, and does not protect shared git objects where `worktreeGroup` +grants access to them. + +Open work, ranked, is on #184. + ## `leadSeats` reports the seat the lead itself holds **What.** For a `subscription: true` profile, `fleet_list`'s row carries a `leadSeats` field when the