Setting restrict_to_workspace = false on an agent
(verified in PostgreSQL agents table and
config.json) should allow that agent's filesystem
tools to access paths outside its workspace.
However, write_file, read_file, and edit tools all
still reject access with:
access denied: path outside workspace
The exec tool correctly allows access to paths
outside the workspace when restrict_to_workspace =
false.
Reproduction
- Set restrict_to_workspace = false for agent
lunexi in both PostgreSQL and config.json
- Attempt to use write_file tool to write to
/tmp/test.txt
- Error: access denied: path outside workspace
- Same operation with exec tool succeeds — it can
write to /tmp/
Expected behavior
When restrict_to_workspace = false,
write_file/read_file/edit tools should allow access to paths outside the agent's workspace, not just
exec.
Root cause (code investigation)
In internal/tools/context_keys.go, the
effectiveRestrict() function is hardcoded to always return true:
func effectiveRestrict(ctx context.Context,
toolDefault bool) bool {
// Multi-tenant security: always restrict
agents to their workspace.
// Agents must not access files outside their
tenant-scoped workspace.
return true
}
This function is called by
write_file/read_file/edit tools (via resolvePath()
in filesystem.go). The toolDefault parameter —
which should reflect the agent's
restrict_to_workspace setting — is completely
ignored. The WithRestrictToWorkspace() context
helper exists (line 269-271) and RestrictFromCtx()
correctly retrieves the override value from
context, but effectiveRestrict() never calls
RestrictFromCtx().
The restrict_to_workspace field in agents table and config.json is never read by filesystem tools
because the check in effectiveRestrict()
short-circuits before any lookup occurs.
Environment
- GoClaw version: (latest from main)
- PostgreSQL 18.3
- macOS
Verification
PostgreSQL query confirms the setting is correctly
stored:
SELECT agent_key, restrict_to_workspace, workspace
FROM agents WHERE agent_key = 'lunexi';
-- lunexi | f |
~/.goclaw/workspace/lunexi
config.json also has restrict_to_workspace: false
for lunexi.
Suggested fix
Modify effectiveRestrict() to actually read the
context override before falling back to
toolDefault:
func effectiveRestrict(ctx context.Context,
toolDefault bool) bool {
if override, ok := RestrictFromCtx(ctx); ok {
return override
}
return toolDefault
}
Setting restrict_to_workspace = false on an agent
(verified in PostgreSQL agents table and
config.json) should allow that agent's filesystem
tools to access paths outside its workspace.
However, write_file, read_file, and edit tools all
still reject access with:
access denied: path outside workspace
The exec tool correctly allows access to paths
outside the workspace when restrict_to_workspace =
false.
Reproduction
lunexi in both PostgreSQL and config.json
/tmp/test.txt
write to /tmp/
Expected behavior
When restrict_to_workspace = false,
write_file/read_file/edit tools should allow access to paths outside the agent's workspace, not just
exec.
Root cause (code investigation)
In internal/tools/context_keys.go, the
effectiveRestrict() function is hardcoded to always return true:
func effectiveRestrict(ctx context.Context,
toolDefault bool) bool {
// Multi-tenant security: always restrict
agents to their workspace.
// Agents must not access files outside their
tenant-scoped workspace.
return true
}
This function is called by
write_file/read_file/edit tools (via resolvePath()
in filesystem.go). The toolDefault parameter —
which should reflect the agent's
restrict_to_workspace setting — is completely
ignored. The WithRestrictToWorkspace() context
helper exists (line 269-271) and RestrictFromCtx()
correctly retrieves the override value from
context, but effectiveRestrict() never calls
RestrictFromCtx().
The restrict_to_workspace field in agents table and config.json is never read by filesystem tools
because the check in effectiveRestrict()
short-circuits before any lookup occurs.
Environment
Verification
PostgreSQL query confirms the setting is correctly
stored:
SELECT agent_key, restrict_to_workspace, workspace
FROM agents WHERE agent_key = 'lunexi';
-- lunexi | f |
~/.goclaw/workspace/lunexi
config.json also has restrict_to_workspace: false
for lunexi.
Suggested fix
Modify effectiveRestrict() to actually read the
context override before falling back to
toolDefault:
func effectiveRestrict(ctx context.Context,
toolDefault bool) bool {
if override, ok := RestrictFromCtx(ctx); ok {
return override
}
return toolDefault
}