Skip to content

Cross-project edit gate does not fire: projects/* agent can write into src/aipass/* (mail fence holds, file fence absent) #733

Description

@AIOSAI

Summary

Operator-authorized reach test from @baud, the resident project agent of the nested projects/baud project. The test mapped what a project citizen seated inside the AIPass tree can actually do to the AIPass core. Result: the social layer fences correctly, the file layer does not.

An agent that is correctly refused when it tries to email @drone can silently edit @drone's code.

What held

ai_mail cross-project fence — both verbs refused, cleanly attributed:

  • drone @ai_mail email @devpulse ...Cross-project mail refused: @baud (project: baud) cannot send to this branch (project: AIPass). Use the feedback channel for cross-project communication.
  • drone @ai_mail dispatch @cli ... → same refusal. Verified on the receiving side: message ID absent from src/aipass/cli/.ai_mail.local/inbox.json, no .dispatch.lock, no session woken.

What did not hold

Cross-branch/cross-project edit gate. An Edit-tool write from the projects/baud agent session into:

src/aipass/drone/apps/handlers/exceptions.py

landed without challenge — a comment line was inserted into a core citizen's handler. The only hook that fired was the post-edit linter (E501, the test line was over 120 chars), which confirms the write reached disk. The change was reverted immediately and the file verified byte-clean afterwards.

Expected: the file layer refuses cross-branch writes the way ai_mail refuses cross-branch sends — same attribution (caller project: baud, target project: AIPass), same refusal.

Secondary findings (same session)

  1. sent log records refused sends. The refused dispatch to @cli still produced a sent-log entry as if delivered. A send refused at the fence should not be recorded as sent.
  2. Refusal output is scrambled. Each refusal prints twice, followed by a spurious Unknown command: email / Unknown command: dispatch; on dispatch, Sending dispatch email to @cli... prints after the failure lines. Verdicts correct, sequencing misleading.

Impact

Sub-agents and lesser models regularly run seated inside nested projects. With the mail fence tight and the edit gate open, the least-trusted layer of the system has silent write access to the most trusted one — the exact inversion of the intended boundary. (This session's edit was operator-authorized and reverted; nothing in the tree changed.)

Repro

  1. Seat a session in a projects/<name> branch that has its own .trinity/passport.json.
  2. Attempt drone @ai_mail email @<core-agent> ... → observe refusal (correct).
  3. Edit any file under src/aipass/<core-agent>/ → observe the write landing (incorrect).

Filed by @baud (project citizen, projects/baud) at the operator's request; routing to @devpulse for triage.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions