Skip to content

tools.fs.workspaceOnly defaults to restricted when unset, contradicting documented default #30927

@deltaclaw

Description

@deltaclaw

Bug: tools.fs.workspaceOnly defaults to restricted even when unset

Observed behavior

When tools.fs.workspaceOnly is not configured (neither globally at tools.fs.workspaceOnly nor per-agent at agents.list[].tools.fs.workspaceOnly), the write and edit tools reject paths outside the agent workspace with:

Path escapes workspace root: /tmp

Expected behavior

Per the type definition in src/config/types.tools.ts, the documented default is false (unrestricted):

export type FsToolsConfig = {
  /**
   * Restrict filesystem tools (read/write/edit/apply_patch) to the agent workspace directory.
   * Default: false (unrestricted, matches legacy behavior).
   */
  workspaceOnly?: boolean;
};

When not set, agents should be able to write outside their workspace (matching legacy behavior).

Root cause

There is a mismatch between the policy resolution layer and the implementation layer:

Policy layer (src/agents/tool-fs-policy.ts:10) correctly resolves undefined to false:

export function createToolFsPolicy(params: { workspaceOnly?: boolean }): ToolFsPolicy {
  return {
    workspaceOnly: params.workspaceOnly === true, // undefined === true → false ✓
  };
}

Implementation layer (src/agents/pi-tools.read.ts:761) treats undefined as true:

function createHostWriteOperations(root: string, options?: { workspaceOnly?: boolean }) {
  const workspaceOnly = options?.workspaceOnly !== false; // undefined !== false → true ✗
  // ...

The !== false guard means only an explicit false unlocks writes. If undefined arrives at this function (through any code path that doesn't go through the policy layer), it silently defaults to restricted.

The same pattern exists in createHostEditOperations and createHostReadOperations.

#28822 partially addressed this for the explicit workspaceOnly: false case, but the default/unset case still behaves as restricted.

Reproduction

# No tools.fs.workspaceOnly set in config
openclaw agent --agent main -m "Write a file at /tmp/test.txt with content 'ok'"
# → "Path escapes workspace root: /tmp"

Agent config:

{
  "id": "main",
  "tools": { "allow": ["*"] }
  // No sandbox, no tools.fs config
}

Global config: no tools.fs section set.

Suggested fix

Either:

A) Change the implementation guard to match the documented default:

const workspaceOnly = options?.workspaceOnly ?? false;

B) Or, if restricted-by-default is the intended secure posture, update the type documentation and ensure the policy layer matches:

// types.tools.ts
workspaceOnly?: boolean; // Default: true (restricted to workspace)

Environment

  • OpenClaw version: 2026.2.27
  • Platform: Ubuntu 24.04 (Linux)
  • Agent sandbox mode: off (default)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions