fix(agent): give file tools the agent workspace as root when no workspace is set (#6722)

* fix(agent): give file tools the agent workspace as root when no workspace is set (#6679)

With no workspace bound, bash/python run in data/agent_workspace, but
RequestAuthority sealed no filesystem root, so every native file tool
failed with "requires a sealed resource root", and an approved
write_file failed with "no sealed resource identity". Seal the agent
workspace instead, and resolve relative paths in _resolve_tool_path
against it rather than the server's cwd.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test: re-seal resource roots when a test swaps the authority owner (#6679)

A no-workspace authority now seals the agent workspace for its owner, so
replace(authority, owner="bob") copied alice's root and was rejected
before the approval-binding check the tests are about.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(agent): only seal a vetted agent workspace as the file-tool root (#6679)

Apply the agent_cwd() check before sealing data/agent_workspace: it must
be a real directory in the readable data subdirs, otherwise no root is
sealed. A symlinked workspace no longer redirects the file tools or the
bash/python launch scope. Tighten the dispatch test assertions to the
exact 'outside the sealed roots' message.

* refactor(agent): vet the no-workspace file root with default_agent_workspace (#6679)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Grzegorz
2026-10-26 09:46:52 -06:00
committed by GitHub
co-authored by Claude Opus 5.5
parent 9d0d3720f4
commit 1000b6582c
7 changed files with 109 additions and 15 deletions
+4
View File
@@ -1068,6 +1068,10 @@ def _resolve_tool_path(raw_path: str) -> str:
if raw_path is None or not str(raw_path).strip():
raise ValueError("path is required")
expanded = os.path.expanduser(str(raw_path).strip())
# Relative paths resolve where bash/python run (agent_cwd), not against
# the server's cwd, which is outside the allowed roots (#6679).
if not os.path.isabs(expanded):
expanded = os.path.join(_AGENT_WORKDIR, expanded)
resolved = os.path.realpath(expanded)
if _is_app_state_path(resolved):