blocking SSH_AUTH_SOCK is not a control: the forge key is an unencrypted file the member can read #184
Open
opened 2026-08-28 01:31:50 +02:00 by ltms
·
5 comments
No Branch/Tag Specified
main
worker/fleetd-612-unita-87807e-1
worker/612-b3-mcpwirings-da2b58-3
worker/612-b2-cb185-176d3a-2
worker/612-b1-completion-457459-1
worker/612-agaps-73a926-2
worker/608-sleeps-3a64ff-3
worker/621-b4520b-1
worker/618-b83894-2
worker/fleetd-615-e05481-5
worker/lead-autocompact-5f1ab2-3
worker/fleetd-613-f85deb-3
worker/fleetd-608-flaky-nudge-test-d0c2d1-3
worker/lead-context-gauge-ad404f-1
worker/gauge-wiring-9158c1-4
worker/redeploy-slowstart-ead0e5-5
worker/charter-bytes-13668c-6
worker/rollover-outcome-291483-2
worker/589-f64303-2
worker/593-1a8025-5
worker/589-fcd2aa-1
worker/568-9fdaa2-3
worker/571-attempted-outcome-5739f7-2
worker/581-completionresolver-cas-sites-0542b7-6
worker/562-loop-health-wiring-test-99611c-5
worker/562-surface-loop-health-7df5cc-4
worker/575-waiter-cleanup-sites-62ad80-1
worker/572-answer-lock-release-46a9ae-5
worker/567-probe-channel-leak-a38fc5-6
worker/551-record-before-send-7cbf56-1
worker/561-listener-fanout-survives-a-throw-61d538-2
worker/555-redeploy-main-flow-seam-65c2f5-2
worker/556-injector-owns-registration-e027a5-1
worker/552-post-restart-mktemp-abort-bc2672-4
worker/553-onstatus-completion-leak-0da881-2
worker/550-shasum-linux-196132-1
worker/538-loop-dies-on-error-4a5eeb-6
worker/426-health-coverage-ef1fd4-4
worker/504-failed-reported-clean-3cfd66-3
worker/537-capturedlog-close-e4c437-2
worker/459-broken-link-targets-cadc17-5
worker/535-appender-leak-fe74c1-1
worker/512-part2-shutdown-detection-434701-9
worker/529-logger-level-sweep-2a5533-8
worker/528-drain-gate-call-site-5de83d-7
charter/forge-mcp-vs-token
worker/521-swap-guard-unpinned-28e931-5
worker/519-probe-test-harness-d25ab8-4
worker/525-logger-level-leak-1b4eb0-6
worker/518-fleetmcp-resolver-wiring-8ef96c-1
worker/512-drain-complete-line-7edd71-3
worker/517-abort-branch-and-jar-id-41b641-2
worker/500-9e52c9-3
worker/509-4912f4-2
worker/511-9a4b23-1
worker/493-479f45-2
worker/505-03f8b2-1
worker/492-followup-detect-unclear
worker/501-a31fa0-7
worker/498-451d1c-5
worker/494-1015ce-2
worker/492-209647-1
worker/489-001902-2
worker/480-relative-handover-path-906323-1
worker/480-b-handover-skill-45bf1f-5
worker/474-followup-source-pin-f54a55-17
worker/474-charter-check-on-reload-f54a55-17
worker/466-quarantine-repeatcount-report
worker/393-opencode-skill-seeding-71854b-13
worker/469-canonical-tool-names-2a472a-16
worker/466-quarantine-escalation-5ae9c1-15
worker/446-hot-exhausted-pattern-0af580-6
worker/464-charter-tool-name-guard-a85635-12
worker/463-listfleet-default-fails-open-f1c76c-11
worker/458-invariant-5-by-purpose-862f9a-10
worker/439-coordinator-row-gate-bc032a-8
worker/449-herdr-protocol-576015-4
worker/450-abstract-spawn-599e1c-5
worker/437-ack-refuses-177d91-1
worker/444-placement-window-feb56a-2
worker/440-helddurable-derived-d462d7-13
worker/425-rework-placement-resolve-c58ba1-9
worker/421-lead-peek-held-msgs-cdbad2-10
worker/435-fixed-policy-cap-fe11de-12
worker/422-gate-state-observability-9e79d6-11
worker/431-memberregistry-live-readers-cdbad2-10
worker/424-architect-slot-hot-038b41-7
worker/422-model-gate-spawn-c29f48-6
worker/425-default-profile-live-f55534-8
worker/415-coverage-wording-2cbf9c-5
worker/416-3ad1da-1
worker/418-588283-3
worker/deterministic-stamp-race-409-3cb7b6-10
worker/armed-reads-live-config-404-ed931f-9
worker/reply-peer-refusal-391-5a34bd-7
worker/models-allowlist-aa9e9b-3
worker/ttl-stamp-race-399-f1122f-8
worker/scrub-receipt-400-316b3e-5
worker/exhaustion-detection-395-105105-6
worker/scrub-abort-394-316b3e-5
fix/scrub-uid-abort
worker/task-scrub-517574-2
worker/t386-clock-bd5b78-4
worker/t384-scrub-813790-5
worker/t381-cc-748314-2
worker/t373-336973-2
worker/t365-3920c5-3
worker/t358-6e989b-1
worker/t355-8b321c-1
worker/fleetd-369-hermetic-git-tests-e8b19a-3
worker/fleetd-368-stale-lead-binding-f5682e-2
worker/fleetd-360-deploy-units-0d3793-1
worker/359-dead-lead-tabs-f1253b-4
worker/362-worktree-skills-c03e51-3
worker/361-coord-visibility-655144-1
362-plugin-visibility-and-drift
worker/errscan-bed2ca-2
worker/amqp-log-identity-bed2ca-2
worker/withdefaults-guard-561704
worker/sleepguard-82076d-1
worker/fd334-9ee1b6-5
worker/fd348-f1ab27-4
worker/fd335-a71c35-1
worker/fd342-174a17-2
worker/fd345-490d0f-3
worker/fleetd-337-5ec7d4-21
worker/fleetd-341-af5a6b-24
worker/fleetd-339-5ca0a2-23
worker/fleetd-338-83a4a1-22
worker/fleetd-333-281f46-18
worker/fleetd-329-11bdbb-16
worker/fleetd-330-2770fb-17
worker/fix-326-50506e-15
worker/fix-324-3e9bbf-14
worker/fix-323-b8287d-13
worker/fix-316b-bd0860-11
worker/fix-318-76ca36-9
worker/fix-317-486aec-8
worker/fix-315-ce47c5-6
worker/fix-307-275890-6
worker/fix-308-b4f664-7
worker/fix-309-ec3939-8
worker/fix-310-7a3974-9
worker/fix-302-52ad0e-9
worker/fix-298-ce1acb-8
worker/fix-297-66bd11-7
worker/fix-296-104622-6
worker/fix-293-bare-closetab-eb22b5-3
worker/fix-280-gone-ask-lapse-bca98e-2
worker/fix-290-reapidle-guard-coverage-9b0dd1-1
worker/fix-285-trust-seed-8f3565-10
worker/fix-284-backend-error-seat-85912c-11
worker/fix-282-chained-ask-e6d0bb-8
worker/fix-283-teardown-leaks-f40dfa-9
worker/fix-281-pin-handler-actions-4921ac-7
worker/audit-rendezvous-lifecycle-d072ae-2
worker/audit-health-placement-1a2476-6
worker/audit-teardown-exits-e207a5-3
worker/audit-launcher-asymmetry-27e370-4
worker/audit-rest-authz-6ca53c-5
worker/investigate-275-abandon-asking-fdef52-8
worker/fix-274-worktree-leak-b0095d-7
worker/fix-273-exhausted-pattern-9665b5-6
worker/fleetd-267-model-check-bd8068-1
worker/fleetd-131-archunit-18b834-7
worker/fleetd-266-sshagent-rename-a014ff-6
worker/fleetd-184-uid-claim-8e1f31-4
worker/fleetd-184-warn-b381ee-10
worker/fleetd-184-docs-be1d12-9
worker/fleetd-257-9bf010-7
worker/fleetd-103-23a113-6
worker/fleetd-247-342356-5
worker/fleetd-116-04dea8-4
worker/fleetd-252-a830e0-3
worker/fleetd-111-7e8673-9
worker/fleetd-155c-f8ef4b-8
worker/fleetd-176-b928ca-3
worker/fleetd-249-7a7878-2
worker/cb248-composition-root-b-9acdf7-15
worker/cb148-envrc-default-fa6c82-12
worker/cb201-unit5-wiring-6c12e6-8
worker/cb241-fallback-echo-1175e9-11
worker/cb149-trust-dialog-2392a5-9
worker/cb134-148-overlay-visible-c9b986-10
worker/cb234-session-id-keyed-04e1fc-1
worker/cb201-unit3-nudge-abdf5c-6
worker/cb201-unit2-policy-c1102c-5
worker/cb201-unit4-outcome-a13bfa-7
worker/cb201-unit1-classifier-91b9b1-4
worker/cb201-227-refine-831980-3
worker/cb175-model-readback-0f085f-1
worker/cb222-charter-tmpdir-17f013-1
worker/cb226-architect-slot-race-cd3aa8-3
worker/cb224-worktree-root-group-024523-2
worker/cb-123-role-demotion-c600f7-2
worker/cb-219-opencode-roots-1f677e-1
worker/cb214-claude-session-id-b9eab4-4
worker/cb213-zdotdir-wrong-process-dd6de4-3
worker/cb211-exhaustion-classification-9546e0-2
worker/cb137-ambiguous-task-4df3d8-4
worker/cb209-agentsessionid-4dfdb6-2
worker/cb185-hostenvnames-2692b5-3
worker/cb206-opencode-sqlite-128718-2
worker/cb185-worktree-group-fc0c99-1
worker/cb-137-ask-ticket-e7760c-2
worker/cb-172-broker-uri-d36ae4-4
worker/cb-175-model-readback-76ead6-3
worker/cb-161-pane-ancestry-293510-1
worker/cb-164-rebase-885863-8
worker/cb-164-empty-scrape-false-success-1a80af-3
fix/cb-197-ticket-ttl-from-completion
worker/cb-189-remote-url-coverage-4692f3-1
worker/cb-185-blockers-027756-4
worker/cb-192-gap-log-11b631-2
worker/cb-633-fix-5f4396-3
worker/cb185-router-d6436d-3
worker/cb185-router-routing-gaps-9e9d33-3
worker/cb185-paneids-992586-2
worker/cb-633-allow-list-union-ed374b-1
worker/cb-157-credential-in-remote-url-496e44-2
worker/cb-641-health-herdr-evidence-8f1f54-6
worker/cb-640-health-msg-evidence-99c9cd-1
worker/cb-642-fleets-status-skill-bbbc40-5
cb-634-ide-mcp
worker/lead-comms-wiring-c014b9-7
worker/lead-mailbox-c19577-6
worker/autocompact-window-82bc2f-5
worker/cb-634-probe-18056f-4
worker/cb635-broker-urienv
worker/cb-632-config-retry-8e0efa-7
lead/cb-622e-claude-md
lead/cb-622-followup
worker/cb-622a-165dff-1
lead/cb-622d-opencode-mount
worker/cb-622b-717c67-2
worker/cb-622c-ab7759-3
worker/cb-617b2-20ca4b-3
worker/cb-617a-5c2f4a-1
worker/cb596-4e49ef-3
worker/cb586-10500c-1
worker/cb-606-b9343a-25
worker/cb604-1445f8-24
worker/cb582-477374-21
worker/cb584-8c2281-22
worker/cb600-e6b9a9-20
worker/cb602-ce257f-19
worker/cb601-b42837-18
worker/cb598-6c7ba7-17
worker/cb599-740fe4-16
worker/cb597-282224-15
worker/cb590fix-185e9a-10
worker/cb528-recovery-race
worker/cb594-96bead-8
worker/cb590-916766-2
worker/cb527-997d99-3
worker/cb592-env-leak-3cbf9c-1
worker/cb588-async-ticket-nudge-3218f7-5
worker/cb578b-9dcb13-6
worker/cb581-d24826-5
worker/m2-u5-ef8c42-15
worker/cb578a-516499-2
worker/cb576-01a04b-17
worker/cb579-lead-tab-acba06-20
worker/cb580-terminal-health-ed6058-21
worker/cb577-f36fdc-18
worker/cb573b-3db06f-16
worker/cb568c-f36fdc-18
worker/cb568-drop-cause-c3ac1c
worker/cb575-cancelled-notification-c3ac1c
worker/m4-sol-a2cbec-3
worker/cb574-async-ask-c3ac1c
worker/cb573-health-model-8ca857-14
worker/cb572-unknown-target-7f2e35-13
worker/u4-700706-9
worker/u3-b9fcb6-6
worker/u2-ef5b68-4
worker/u1-469dce-1-clean
worker/u1-469dce-1
worker/cb-564-health-events-70cf7e-2
worker/cb-565-recycle-drops-role-98e58f-3
worker/cb-563-missing-reply-df2866-1
worker/cb-562-readiness-gate-silent-6c23c9-3
worker/cb-560-architect-presence-da8155-1
worker/cb-561-architect-silent-off-a71cab-2
worker/cb-548-bind-architect-slot-fe1b8c-1
worker/parity-overlay-settings-5fb711-1
secrets-central-store
cb-559-hot-key-correction
cb-557-fleet-role-pools
worker/cb-553-maxload-explicit-spawn-305ee3-6
worker/cb-551-idle-lead-heartbeat-f1633c-1
worker/cb-544-drain-preserves-worktree-925fad-3
worker/cb-552-docs-sync-1cb9cf-4
worker/cb-548-rendezvous-guard-rebased
worker/cb-548-rendezvous-guard-116b53-10
worker/cb-548-authz-v2-586df6-8
worker/cb-548-authz-264363-5
salvage/cb-528b-codex-home
salvage/cb-528a-codex-launcher
CB-518-primary-flow
feature/peer-launcher-spi
cb-103-injector
v1.1.0
v1.0.0
Labels
Clear labels
blocked
needs-live-proof
ready-to-delegate
silent-default
Cannot start until something else lands. The body says what.
Merged and green, but never shown working on the running daemon. Not the same as done.
Scope, files and acceptance criteria are written. A worker can be briefed from the body alone.
A feature that compiles, passes tests, and ships turned off. Nine recurrences and counting.
No Label
Milestone
No items
No Milestone
Projects
Clear projects
No project
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: fleet/fleetd#184
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found while proving the
memberCredentials.policy: allow-listflip on 2026-08-28. The scrub works. The thing it was believed to be protecting is reachable another way.What was believed
#110 and the
sshAuthSock: blockdecision rest on this premise:SSH_AUTH_SOCKis a live handle to the operator's ssh-agent, so blocking it stops a member signing with the operator's keys. I stated, in a review comment on #177 and in a brief, that~/.sshholds no private key file at all and the forge identity exists only inside the agent.That was wrong. I had looked only in
~/.ssh.What is actually true
A live
opencodemember, spawned underpolicy: allow-list, reported:…and then pushed to the forge over SSH successfully.
The reason:
~/.ssh/configis fourIncludelines pointing into a shared-env directory, and the included files setIdentityFilefor the forge. Checking that file:A member runs as the same OS user. So it reads the key file directly. The agent is irrelevant to it.
Why this matters
sshAuthSock: blockis cosmetic on this host. It blanks a variable that SSH does not need. A member has full SSH access to the forge — and to every other host those included configs define an identity for, which is a large list.memberCredentialsscrub removes environment variables. It cannot remove a file. #157 was a token in.git/config; this is a key in~/Drive00/.... Both walk straight past a control that only ever looked at the environment.The general shape, again
The enumeration keeps being of the wrong thing. #596 enumerated a file and missed an environment. This enumerated an environment and missed a file. A control that names a channel will always be walked around by the channel nobody named.
The useful question is not "which variables do we blank?" but "what can a process running as this user reach?" — environment, files, sockets, keychain, and the ssh_config graph.
Suggested direction
Nothing here is a quick fix, and I have not implemented any of it.
allow-list, resolvessh -Gfor the configured forge host and, if it yields a readableidentityfile, log a WARN saying SSH access is NOT blocked by this policy. The daemon should not let an operator believesshAuthSock: blockdid something it did not.What the flip DID achieve — not nothing
Worth keeping in view. Under
allow-listthe daemon blanked 27 credential-shaped variables, measured:That includes the AWS
AdministratorAccesspair from #144 — a genuine, large reduction. This ticket is about not overstating it.Related
SSH_AUTH_SOCKdecision this disproves the premise of.I put this to an architect as a design question — "what is the honest security boundary we can actually build, and what should we stop claiming?" — rather than as an implementation job. Its answer is below, checked and endorsed. I have started the top-ranked item.
1. What a same-uid member can reach today
The honest threat model: a same-user member is a trusted local process. It is not a sandbox.
policy: allow-listruns a lateZDOTDIRscrub.ssh_config→IdentityFile→ passphrase-free key. Also CLI auth stores and secret scripts.sshAuthSock: blockblanks one env var.credential.helperand rewrites a parsed SSH origin to HTTPS.sshdirectly.The concrete bad path, start to finish: the scrub blanks
SSH_AUTH_SOCK→ git starts ssh → ssh reads user config → it opens the readableIdentityFile→ the forge accepts the operator's key. The gate closes lead → child environment inheritance. It does not close member → filesystem → credential. That is the one-way-gate shape again: it closes only the direction the original incident came from.2. Is any control possible without changing uid?
No. Not through ordinary Unix permissions. Environment cleanup, worktrees, config rewrites and tool permissions reduce accidents. A member that can run commands bypasses all of them.
A real boundary inside one uid needs a different OS mechanism — mandatory access control, a container with narrow mounts, or a VM — denying the operator's home, lead sockets and process inspection, allowing only the worktree and scoped credentials. That is a new execution model, not a better name list.
The existing path is #185's second herdr under a different user. That protects files, sockets, process environment and process memory through OS permissions. It does not protect argv, and it does not protect shared git integrity where
worktreeGroupgrants access to shared objects and refs — a separate member-owned clone would be needed for that.3. What we must stop claiming — started
The shipped
fleetd.example.yamlcurrently says:That is measured false. On 2026-08-28 a member with
SSH_AUTH_SOCKblanked pushed to the forge over SSH successfully. The livefleetd.yamlwas corrected at the time; the committed example never was, so the false claim is the one every new operator reads.Delegated now. The corrected wording says what the setting does (omits the inherited agent path from the member environment), what it does not do (does not deny same-uid access to the socket, does not block readable key files, git over SSH may still work), and that the block stays because it is free — but is not a control.
The wiki needs the same treatment:
memberCredentialscontrols ambient environment propagation, not credential access; a worktree isolates changes and normal git routing, not filesystem access; same-user mode assumes trusted members.The architect also suggests a later rename to
sshAgentEnv: omit|inherit, sinceblockstates more than it does. I have not done that — it is a schema change and needs its own ticket.4. Ranked by value gained over work needed
memberHerdrSocketwith a different user (#185). The smallest existing option that creates a real boundary. Acceptance: the operator's home and lead sockets unreadable; only scoped member inputs readable; the shared-git limit stated.Scope of the architect's work
Read-only. No file changed, no test run, and it said plainly that no peer architect was reachable, so this is one checked position rather than an agreed one.
Keeping this open for items 2–4. Item 1 will be linked when it lands.
Item 1 progress — the "write down the truth" half is done, the startup warning is in flight.
Done: the config no longer lies
PR #264, merged as
b5ddbe5, with a follow-up ina2b8caf. ThesshAuthSockentry infleetd.example.yamlnow says what the setting does (omits the inherited agent path), what it does not do (does not deny same-uid access to the socket, does not block readable key files, git over SSH may still work), and where the real boundary is.The false claim it replaced — "Blocking it breaks git over SSH inside members" — had been in the shipped example since before the measurement that disproved it. The live
fleetd.yamlwas corrected on 2026-08-28; the committed example was not, so the false version is the one every new operator has been reading for a week.One thing worth recording about the fix itself. The first cut removed the false claim and also removed a true one next to it: that
SSH_AUTH_SOCKis a live handle to the agent, so a member holding it can sign with every key the agent holds. Without that sentence the entry reads as if the knob does not matter — and an operator has no reason left not to set it toallow.So correcting an overclaim had produced an underclaim. I restored the sentence and split the two ideas: blocking it does not contain a member, but allowing it hands one a signing capability for no gain, so keep the block. The entry now also carries the measurement and the original mistake (looking only in
~/.ssh, which holds nothing but fourIncludelines).Done: the wiki states the frame
Added a Features entry, "What a member can actually reach — the honest boundary". It carries the per-channel table from the design above, the proven path to the operator's key, and the plain statement that no meaningful boundary exists inside one uid.
It also names the recurring shape, because this is the third time it has come up 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.
In flight: the startup line
A member is now working on the second half of item 1 — one INFO line at startup saying members run as the same OS user, what follows from that, and that
memberHerdrSocketis the existing route to a real boundary.The part I was careful to brief explicitly: when
memberHerdrSocketIS set, the line must change and must not claim a boundary fleetd cannot verify. fleetd cannot see the uid of a process on the other end of a socket, so it can say members are routed to a separate herdr and that whether that herdr runs as a different user is the operator's to confirm. Replacing one false assurance with a new one would defeat the whole ticket.Still open, unchanged
Items 2, 3 and 4 from the ranked list. Item 3 (make the normal git route fail closed when the HTTPS rewrite fails) is the next one with a real cost/benefit case, and it is attribution and hygiene rather than isolation — direct
sshstays open whatever we do there.The
sshAgentEnv: omit|inheritrename is not done. It is a schema change and wants its own ticket.Item 1 is done — merged as
fa97f59(PR #265).fleetdnow logs the member trust model at startup, and the message changes whenmemberHerdrSocketis set. The unset branch says plainly that members run as the same OS user and can read any file that user can read, whatevermemberCredentialssays.Also shipped earlier under this ticket:
b5ddbe5+a2b8cafremoved the false claim that blockingSSH_AUTH_SOCKbreaks git over SSH, and kept the true half — the socket is a live handle to the agent, so a member holding it can sign with every key the agent holds.New item 5 —
HerdrPeerLaunchermakes the exact claim this ticket removesFound by the worker on #265, confirmed by me in the code.
HerdrPeerLauncher.warnUnknownMemberEnvironmentlogs:fleetdcannot see the uid at the other end of a unix socket. The "so" is an assumption, not a fact. The same claim is stated as a definition in thememberHerdrSocketConfigured()javadoc (line ~1630) and in the class javadoc (line ~120).Why this matters, and which direction is harmful. If an operator points
memberHerdrSocketat a second herdr running as the same user — a reasonable config, two herdr instances for pane isolation — then members inheritfleetd's own environment. The real credential gap is exactly the count the WARN just told the operator to disregard. A known exposure is reported as an unknown one. That is an under-report, and it is the direction that costs something.It also now contradicts the line merged in this ticket: the startup report says "fleetd cannot see that herdr's uid", and this WARN says "so member panes run under a different OS user". Both go to the same log.
The fix is wording, not behaviour. The branch should still be taken — reporting on the wrong process is still the risk — but it must say "fleetd cannot confirm the uid, so treat the member environment as unknown", not "members run as a different user". Blast radius is small: no test asserts that WARN's text.
Items 2–4 remain open.
Split out #266 —
memberCredentials.sshAuthSock's value names (block/allow) make the same kind of claim this ticket is about, one layer down.blocknames an effect fleetd does not have: it omits the variable, it does not deny same-user access to the socket.Kept out of this ticket because it is a config rename needing a read-both shim, not a prose fix. It carries a real risk this ticket does not: the live config on this host uses the old spelling, so the shim is load-bearing.
Item 5 (the
HerdrPeerLauncheruid claim) is delegated and in progress.Item 5 is done — merged as
27aefbf(PR #269). All four sites inHerdrPeerLaunchernow say fleetd cannot confirm what OS user the second herdr runs as, instead of asserting it does. No behaviour change. The WARN still states the honest conclusion, so this did not trade an overclaim for an underclaim.I re-ran the mutation proof myself rather than trusting the report: reintroducing the old false claim turns the new test red. Restored,
git diff --exit-codeclean, full build 1265 tests green at that point (1269 after the later merges).On the 10 further "same shape" sites the implementer reported
I checked three of them in the code —
GitWorktrees.shareRootWithGroup,EnvAllowListScrub.shareWithGroup, andClaudeCodeLauncher.writeCharterFile. I am not filing them, and I think that is the right call.Every one of them assumes a different OS user and therefore does more accommodation: share the group, make
worktreeRoottraversable, keep the charter out of fleetd's 0700 tmpdir. If the assumption is wrong and the member is the same user, the extra work is harmless — it was already reachable. The claim is inaccurate, but being wrong costs nothing.That is the opposite of the WARN this ticket just fixed, where the wrong assumption caused a real exposure to be reported as unknown. The direction is what makes it a defect, not the phrasing.
Worth recording because two workers disagreed here. A separate audit of exactly this shape, run in parallel, read
EnvAllowListScrubin full andGitWorktreesin part and reported no findings — it was applying a "being wrong must cost something" filter. The implementer's brief asked it to report the shape without repeating that filter, so it matched on the phrase. The audit was right; the difference came from my briefing, not from either worker's care.The remaining sites are still inaccurate, and a future maintainer could lean on the premise in the harmful direction. Cheap mitigation rather than a fan-out: soften them whenever those files are next touched, matching
Fleetd.reportMemberTrustModel.Items 2–4 remain open. #266 (the
sshAuthSockvalue rename) is done and closed.