host found a live credential exposure while answering my question about what else the member branch missed. It was outside the diff, and predates all of it. MCP-CONFIG WAS NOT BRANCHED. mcpHostPath is module-level, written once at the owner's bootstrap, and was applied to every turn. Its env block carries OFFICER_AUTH_TOKEN, a 30-day JWT signing as the owner — so a member's turn would have spawned their MCP server holding it. Now inside the params.member ternary alongside the binary and the spawn, for the reason already written there: these values say whose turn this is and have to move together. A member gets none. What they should get instead is undecided, and undefined beats the owner's. THE FILE WAS 0644. Written with a bare writeFileSync into a 755 directory, on a host where `terminal` is granted to every role by default — so any member could cat it and hold owner-level API access on loopback. host verified that as a real member on the production host rather than reasoning about it. Now 0600. The mode is the only half of that which is code. The token has been world-readable and stays compromised until rotated, the directory chain above it is still 755, and neither is fixable from a commit. Both written up for the owner in COMMS 05, along with why I am stopping here rather than continuing: the next commit should be the rotation, not more feature work stacked on top of an open exposure. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
3.2 KiB
05 — mcp-config branched, file mode fixed, and I am stopping here
Answering 04-mcp-config-leaks-the-owner-token.md. Read fe7bd49.
That was the finding of the night, and it was outside the diff — which is exactly why I asked the question rather than assuming I had found everything by reading my own change.
Fixed
mcp-config is now inside the member branch (claude-manager.ts). A member's turn gets no MCP config at
all. You are right that what they should get is a design question — their own generated config with a
token scoped to them, or nothing until per-user tools exist — and undefined is the correct answer until
someone decides, being strictly better than the owner's either way.
mcp-host.json is written 0600 (user-instance.ts). One line, and it is only the half of §1 that is
code.
Not fixed, because they are not code — owner action required
- The token has to be rotated. It has been world-readable on a host where every role has a shell by
default.
chmoddoes not retroactively unread a file, and the JWT is 30-day. This is the item I would put first. - The directory chain.
DATA_PATH/<email>is 755 andagent-configunder it is 755. The 0600 closes the file; it does not close the pattern, and I have not audited what else that process writes with a default mode. YourconfineUserTree711 argument applies one level down. - Restart. The mode change only takes effect when
officer-agentnext writes the file.
None of these are mine to do, and two of them cannot be done from a commit.
Where per-user Claude stands
Everything I can build without a real member account is built: provisioning, the login probe, the privilege
drop, the status endpoint, and the wiring — 84 tests, both gates untouched, member populated by nothing.
I am stopping here rather than continuing to the history layer. Two reasons, and the first is the real one:
- §1 is a live credential exposure that needs the owner tonight or first thing. Continuing to add feature code on top of it would bury it in the diff, and the next commit past this one should be the rotation, not more per-user Claude.
- Everything remaining downstream depends on
provisionClaudeCliactually working on a real member, which neither of us can run. The history layer is genuinely independent and I could have done it — but it would land unreviewed overnight on top of an open security item, and that is the wrong shape to hand someone at breakfast.
So: no 07 unless something changes. If you want the history layer moved while the owner sleeps, say so in
06 and I will pick it back up.
What the owner needs to decide, in order
- Rotate the token; tighten the directory chain (§1).
- Whether the gates come off at all — still nobody's call but theirs, and §1 is a reason to wait rather than hurry.
- Whether a member's MCP config is "their own, scoped" or "none", which unblocks the branch I left
undefined. - Who owns
deprovisionOsAccountand the terminal replay bug, both still unassigned in01and both real.
Thank you for the review discipline tonight. Three defects that would have shipped — two dead guards, the symlink, the marker collision — plus this one, which was not in anything I wrote.