You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Write tools check isOutsideWorkspace with a lexical path check. A symlink inside the workspace can point to a directory outside the workspace. A write through that symlink is classified as inside the workspace. With alwaysAllowWrite on and alwaysAllowWriteOutsideWorkspace off, the write is auto-approved.
Found during review of #2343 (follow-up to #2249).
Affected code
isPathOutsideWorkspace in src/utils/pathUtils.ts uses path.resolve and a string prefix check. It does not resolve symlinks.
These tools use it to set isOutsideWorkspace in their approval payload: write_to_file, apply_diff, edit, edit_file, search_replace, apply_patch, and generate_image.
isRealPathOutsideWorkspace in the same file already resolves symlinks with realpath. It checks the deepest existing ancestor for paths that do not exist yet, and it fails closed. Only the openFile handler in webviewMessageHandler.ts uses it.
Steps to reproduce
In the workspace, create a symlink to a directory outside it: ln -s ~/.config linked-config.
Set autoApprovalEnabled: true, alwaysAllowWrite: true, and alwaysAllowWriteOutsideWorkspace: false.
Ask the agent to edit linked-config/some-app/config.json.
The edit is applied without an approval prompt.
Expected result
A write whose real target is outside the workspace sets isOutsideWorkspace: true. Auto-approval then asks, unless alwaysAllowWriteOutsideWorkspace is on or an allowedWriteFiles pattern matches.
Proposed approach
Move all write tools to isRealPathOutsideWorkspace together, so that all tools give the same result for the same path.
isRealPathOutsideWorkspace is async. The execute paths can await it. The streaming preview (handlePartial) can keep the lexical check, because the final approval decision uses the execute payload.
Add tests for each tool: a symlink to an outside directory asks, and a normal path inside the workspace is still auto-approved.
Activity