sec(mcp): launch pwd is the credential boundary — dir= must never become a token selector #90

Closed
opened 2026-07-15 14:46:39 +00:00 by hexajon · 2 comments
hexajon commented 2026-07-15 14:46:39 +00:00 (Migrated from codeberg.org)

Decision

Decision (2026-07-15): an agent must be prevented from crossing outside the launch pwd and using auth tokens it finds in other checkouts on disk. The launch scope is the credential boundary. Credential-borrowing dir= is an anti-goal, not a missing feature — this inverts #87 (closed by this decision) and puts #59's ask in question (flagged there for decision).

Demonstrated the same day: I was in an unauthed clone, needed forge access, and the working path was cd into a different, correctly-authed checkout and running CLI ops on its token. Nothing in madtea defines or defends against that: the agent was one cd away from every identity configured anywhere on the disk it can read. The sanctioned remedies are #88 (know at connect) + #89 (authenticate the launch scope in-session) — never token discovery.

Current exposure

  • MCP surface: the git-plane dir= tools resolve per-repo credentials for foreign clones. The sanctioned foreign-repo flow (worktree add → finish branch=, ADR 0019) legitimately depends on this — but its credential scope has never been stated: which tools may resolve a foreign checkout's token, for which operations, and why those and no others.
  • CLI surface: the CLI resolves whatever the cwd's git config says, by design (it's the human surface, and humans own their disk). The ADR 0009 steering hook pushes agents toward MCP, but MCP-side there is no boundary to land on — so steering alone doesn't close anything.

Ask

  1. Define the boundary in an ADR: launch scope is the credential scope for the MCP server. dir= is a repo/tree selector, never a token selector. Enumerate the explicit carve-out for the worktree→finish foreign-repo flow (exactly which tools, exactly which ops) rather than leaving it implicit.
  2. Enforce it: an API-plane operation whose credentials would resolve from outside the launch scope is refused with an explaining error that points at the sanctioned remedies (madtea auth login in the launch dir; #89 once it exists). Same refusal-with-remedy shape as the foreign-primary guards.
  3. Pin it: a parity-style test records which tools are allowed foreign-credential resolution, so a new tool can't quietly widen the boundary.

Needs decision

  • Reconciliation with #59, whose ask ("any agent on the system should be able to file a bug against any locally-cloned, authed repo") reads as the opposite of this decision.
  • Whether the CLI stays entirely free (human surface) or grows an opt-in agent-mode guard; the default assumption here is CLI stays free and the boundary is MCP-side + steering.

Acceptance

  • Attempted foreign-credential resolution on a non-carve-out MCP tool → refusal naming the boundary and the remedy.
  • ADR merged documenting scope + carve-outs; parity test enforces the tool list.
  • #59 disposition decided and recorded.

Refs #87 (inverted by this decision), #59 (needs reconciling), #88, #89 (the sanctioned remedies), ADR 0009, ADR 0019.

## Decision Decision (2026-07-15): an agent must be **prevented** from crossing outside the launch pwd and using auth tokens it finds in other checkouts on disk. The launch scope is the credential boundary. Credential-borrowing `dir=` is an anti-goal, not a missing feature — this inverts #87 (closed by this decision) and puts #59's ask in question (flagged there for decision). Demonstrated the same day: I was in an unauthed clone, needed forge access, and the working path was `cd` into a *different, correctly-authed* checkout and running CLI ops on its token. Nothing in madtea defines or defends against that: the agent was one `cd` away from every identity configured anywhere on the disk it can read. The sanctioned remedies are #88 (know at connect) + #89 (authenticate the launch scope in-session) — never token discovery. ## Current exposure - **MCP surface:** the git-plane `dir=` tools resolve per-repo credentials for foreign clones. The sanctioned foreign-repo flow (worktree add → finish `branch=`, ADR 0019) legitimately depends on this — but its credential scope has never been *stated*: which tools may resolve a foreign checkout's token, for which operations, and why those and no others. - **CLI surface:** the CLI resolves whatever the cwd's git config says, by design (it's the human surface, and humans own their disk). The ADR 0009 steering hook pushes agents toward MCP, but MCP-side there is no boundary to land on — so steering alone doesn't close anything. ## Ask 1. **Define the boundary in an ADR:** launch scope is the credential scope for the MCP server. `dir=` is a repo/tree selector, never a token selector. Enumerate the explicit carve-out for the worktree→finish foreign-repo flow (exactly which tools, exactly which ops) rather than leaving it implicit. 2. **Enforce it:** an API-plane operation whose credentials would resolve from outside the launch scope is refused with an explaining error that points at the sanctioned remedies (`madtea auth login` in the launch dir; #89 once it exists). Same refusal-with-remedy shape as the foreign-primary guards. 3. **Pin it:** a parity-style test records which tools are allowed foreign-credential resolution, so a new tool can't quietly widen the boundary. ## Needs decision - Reconciliation with #59, whose ask ("any agent on the system should be able to file a bug against any locally-cloned, authed repo") reads as the opposite of this decision. - Whether the CLI stays entirely free (human surface) or grows an opt-in agent-mode guard; the default assumption here is CLI stays free and the boundary is MCP-side + steering. ## Acceptance - Attempted foreign-credential resolution on a non-carve-out MCP tool → refusal naming the boundary and the remedy. - ADR merged documenting scope + carve-outs; parity test enforces the tool list. - #59 disposition decided and recorded. Refs #87 (inverted by this decision), #59 (needs reconciling), #88, #89 (the sanctioned remedies), ADR 0009, ADR 0019.
hexajon commented 2026-07-15 15:14:55 +00:00 (Migrated from codeberg.org)

ADR 0027 is merged (PR #92, docs/adr/0027-launch-scope-credential-boundary.md) — the 'ADR merged documenting scope + carve-outs' half of this issue's acceptance is done, refined per the owner's follow-up ruling: TWO enumerated crossings (contribute = the ADR 0019 worktree→finish flow; report = issue filing bound to a foreign clone's own origin), both bound to the target checkout's own remote. Remaining here: the refusals themselves and the parity test pinning which tools may resolve foreign credentials. Note #94 before building the refusals: the contribute carve-out is currently BROKEN for repo-config-authed targets (GetConfigForDir never reads dir-local madtea.token), so enforcement work should land the sanctioned resolution shape and the refusals together.

ADR 0027 is merged (PR #92, docs/adr/0027-launch-scope-credential-boundary.md) — the 'ADR merged documenting scope + carve-outs' half of this issue's acceptance is done, refined per the owner's follow-up ruling: TWO enumerated crossings (contribute = the ADR 0019 worktree→finish flow; report = issue filing bound to a foreign clone's own origin), both bound to the target checkout's own remote. Remaining here: the refusals themselves and the parity test pinning which tools may resolve foreign credentials. Note #94 before building the refusals: the contribute carve-out is currently BROKEN for repo-config-authed targets (GetConfigForDir never reads dir-local madtea.token), so enforcement work should land the sanctioned resolution shape and the refusals together.
hexajon commented 2026-07-16 14:03:41 +00:00 (Migrated from codeberg.org)

As these are locally cloned repos with code forge credentials the user/agent controls, the limited two exception carve out is an acceptable boundary softening. The very "on-rails" worktree finish flow, and the "need to report a bug" are the only outside pwd paths allowable.

As these are locally cloned repos with code forge credentials the user/agent controls, the limited two exception carve out is an acceptable boundary softening. The very "on-rails" worktree finish flow, and the "need to report a bug" are the only outside pwd paths allowable.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
sixfold-space/madtea#90
No description provided.