Skip to content

subagent tool: no cwd isolation — children inherit the session cwd, can read sibling repos + confabulate ownership #20

Description

@rz1989s

Summary

The subagent tool spawns child subagent sessions in the pi session cwd, not the dispatch target's cwd. The "Work from: …" prose in the dispatch task text is not enforced. A child can therefore read (and potentially write) any repo reachable from the session cwd, including unrelated sibling projects. Additionally, because the child can see other sessions' on-disk artifacts (e.g. another project's .superpowers/sdd/ ledger), it can confabulate ownership of pre-existing work it merely read.

Evidence (surfaced while dogfooding armory-fleet on itself for SPEC-6-3)

  • A pi session was started in ~/local-dev/getpipher/keystone (a separate, active SDD run in another pane). armory-fleet work was driven from that session by pasting an armory-fleet handoff.
  • Tasks 1–7 subagents honored the "Work from: ~/local-dev/getpipher/armory-fleet" prose and cd'd there correctly.
  • The Task 8 subagent, spawned in the keystone cwd, read keystone's .superpowers/sdd/ ledger (a parallel SDD run) and falsely claimed credit for "keystone Task 7" (commit 1ec048e) in its response text — even though that commit was made by the separate keystone session ~2 min before the armory-fleet subagent ran. The subagent's actual report file was armory-fleet-only (0 keystone mentions) and its real commit (6e0be06) was clean armory-fleet. No cross-repo write occurred — the fault was a confabulation, not a real leak.

Impact

  • Low in practice (this instance): zero cross-session writes; the armory-fleet commit was clean and the sibling session's work was intact. The only artifact was a misleading response text, caught by verifying the report file + git.
  • Higher in principle: a subagent scoped to project X can read/write sibling repos reachable from the session cwd. If a future subagent goes rogue (or just gets confused), it could make real commits in the wrong repo. The normal usage pattern (start pi in the project you're working on → session cwd == dispatch target) doesn't trigger it; the edge case is driving project X from a session whose cwd is project Y.

Proposed fix

Add a cwd concept the child subagent cannot escape:

  1. The subagent tool accepts an explicit cwd (default = the dispatching project's cwd, NOT the session cwd).
  2. The child's working directory is pinned to cwd; operations (read/write/bash/git) outside it are rejected or sandboxed.
  3. Equivalently: pin the child session's ResourceLoader + cwd to the dispatch target so it cannot even see sibling repos — which also prevents the confabulation at the source (can't claim credit for what it can't see).

This deserves its own brainstorm → spec → plan (default-cwd semantics, panel Run-action interaction, relative-skill-path implications), not a hot-patch.

Repro

  1. Start pi in repo A (~/local-dev/<org>/A).
  2. From that session, dispatch subagent({ task: "<work for repo B at ~/local-dev/<org>/B>" }) where the task text says "Work from: ~/local-dev//B".
  3. Observe the child spawns in A's cwd (the session cwd); it can ls/read A's files (and any sibling) despite the task targeting B.
  4. If A has SDD/agent artifacts on disk, the child may read + reference them in its response (confabulation risk).

Mitigation in the meantime

Dispatch prompts explicitly instruct: "cd to FIRST; do not read/write/commit in any other directory; ignore any .superpowers/sdd/ or repo artifacts not in ; claim only work you actually performed." Sufficient for trusted single-session use; not a substitute for the cwd-isolation fix.

Proposed disposition

Tracked enhancement — candidate for a dedicated fix(subagent): patch or a SPEC-6-4 item, not a v0.12.0 blocker (zero actual harm; normal usage doesn't trigger it).

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions