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>
59 lines
3.2 KiB
Markdown
59 lines
3.2 KiB
Markdown
# 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
|
|
|
|
1. **The token has to be rotated.** It has been world-readable on a host where every role has a shell by
|
|
default. `chmod` does not retroactively unread a file, and the JWT is 30-day. This is the item I would put
|
|
first.
|
|
2. **The directory chain.** `DATA_PATH/<email>` is 755 and `agent-config` under 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. Your `confineUserTree` 711 argument applies one level down.
|
|
3. **Restart.** The mode change only takes effect when `officer-agent` next 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 `provisionClaudeCli` actually 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
|
|
|
|
1. Rotate the token; tighten the directory chain (§1).
|
|
2. Whether the gates come off at all — still nobody's call but theirs, and §1 is a reason to wait rather than
|
|
hurry.
|
|
3. Whether a member's MCP config is "their own, scoped" or "none", which unblocks the branch I left
|
|
`undefined`.
|
|
4. Who owns `deprovisionOsAccount` and the terminal replay bug, both still unassigned in `01` and 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.
|