From bb49b8781003087a0411a0f49dc94f4d01ff657e Mon Sep 17 00:00:00 2001 From: viettranx Date: Thu, 23 Apr 2026 19:16:05 +0700 Subject: [PATCH] refactor(tools): use write-allowed paths for edit and shell execution - edit tool now calls allowedWriteWithTeamWorkspace to prevent cross-chat writes - shell tool upgraded to use write-allowed prefixes for cwd resolution - Prevents shell commands from accessing/mutating peer chat workspaces via absolute paths - Add clarifying comment on shell's write-safety model --- internal/tools/edit.go | 2 +- internal/tools/shell.go | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/internal/tools/edit.go b/internal/tools/edit.go index f7370066..a08c5b44 100644 --- a/internal/tools/edit.go +++ b/internal/tools/edit.go @@ -170,7 +170,7 @@ func (t *EditTool) Execute(ctx context.Context, args map[string]any) *Result { if workspace == "" { workspace = t.workspace } - allowed := allowedWithTeamWorkspace(ctx, t.allowedPrefixes) + allowed := allowedWriteWithTeamWorkspace(ctx, t.allowedPrefixes) resolved, err := resolvePathWithAllowed(path, workspace, effectiveRestrict(ctx, t.restrict), allowed) if err != nil { return ErrorResult(err.Error()) diff --git a/internal/tools/shell.go b/internal/tools/shell.go index 563661ca..6726ea71 100644 --- a/internal/tools/shell.go +++ b/internal/tools/shell.go @@ -323,7 +323,12 @@ func (t *ExecTool) Execute(ctx context.Context, args map[string]any) *Result { if wsBase == "" { wsBase = t.workspace } - allowed := allowedWithTeamWorkspace(ctx, nil) + // Shell is an arbitrary executor — a cross-chat cwd would let the + // command mutate files in another chat's workspace. Enforce the + // stricter write-allowed prefixes (team root excluded) to block + // cross-chat cwd even for "read-only" commands like cat, since we + // cannot prove the shell command will not write. + allowed := allowedWriteWithTeamWorkspace(ctx, nil) resolved, err := resolvePathWithAllowed(wd, wsBase, true, allowed) if err != nil { return ErrorResult(err.Error())