Skip to content

[Feature]: Path-scoped RWX permissions for exec and file tools #39979

@subrih

Description

@subrih

Summary

Replace the binary-level exec allowlist with a path-keyed RWX permission map so agents
inherit read/write/execute rights from the target path, not from which binary is running —
identical in spirit to Unix DAC.

Problem to solve

Today, allowing /bin/ls on ~/workspace also allows /bin/ls on ~/.openclaw and
~/.ssh. There is no way to scope execution by path. The only guardrail is SOUL.md prompt
instructions — which are not enforcement. As documented in #12202, model compliance varies
across providers and A2A requests can silently bypass user-facing refusals.

This is especially acute in single-OS-user setups (gateway + agent sharing the same
account) where the tool execution layer is the only practical enforcement boundary.

Proposed solution

Replace the binary-level allowlist with a path-keyed RWX permission map. The binary is
irrelevant; what matters is what operations are permitted on a given path:

"permissions": {
  "filesystem": {
    "rules": {
      "~/workspace/**":       "rw-",
      "~/workspace/bin/**":   "r-x",
      "~/documents/**":       "rw-",
      "/tmp/openclaw/**":     "rwx"
    },
    "deny": [
      "~/.openclaw/**",
      "~/.ssh/**",
      "~/.gnupg/**"
    ],
    "default": "---"
  }
}

Permission bits:

  • r — agent may read the path (file tools: read; exec: cat, grep, ls, find, etc.)
  • w — agent may write/modify the path (file tools: write, edit; exec: cp, mv, rm, etc.)
  • x — agent may execute files at this path (exec tool only)
  • - — deny that operation

Evaluation logic:

  1. For any tool invocation (read, write, edit, exec), extract the target path(s)
  2. Find the most specific matching rule (longest glob wins)
  3. Check the required permission bit for the operation type
  4. If the bit is -, or the path matches a deny entry → block before execution
  5. deny always wins over rules on conflict
  6. Unmatched paths fall through to default (recommended: ---)

This applies uniformly across file tools and exec — no special-casing per binary.

Alternatives considered

A binary-scoped model (e.g. "allow /bin/cat on these paths") is incomplete:

  • It requires enumerating every binary that could touch a path
  • Shell builtins, aliases, and piped commands make binary extraction unreliable
  • The path is the resource being protected — that's where the policy belongs

Path-keyed RWX is simpler to reason about, simpler to configure, and matches the mental
model operators already have from Unix.

Impact

Affected: All single-OS-user gateway+agent deployments (the recommended/default setup)
Severity: Blocks meaningful security hardening — there is currently no reliable way to
restrict which paths an agent can touch via exec
Frequency: Constant — every exec invocation operates under an all-or-nothing binary allowlist
Consequence: Agents with exec access to any binary can reach sensitive paths
(~/.openclaw, ~/.ssh, credentials/) — the only mitigation today is prompt instructions,
which are demonstrably unreliable across model providers and invisible to A2A callers

Evidence/examples

Example 1 — Allow most system binaries but restrict specific ones:

"permissions": {
  "filesystem": {
    "rules": {
      "/usr/bin/**":          "r-x",
      "/usr/bin/grep":        "r--",
      "/usr/bin/curl":        "---",
      "~/workspace/**":       "rw-",
      "~/workspace/bin/**":   "r-x"
    },
    "deny": ["~/.ssh/**", "~/.openclaw/**"],
    "default": "---"
  }
}

/usr/bin/lsr-x (inherits wildcard)
/usr/bin/grepr-- (readable, not executable — more specific rule wins)
/usr/bin/curl--- (explicitly locked out)
~/.ssh/id_rsa → blocked (deny wins over everything)

Example 2 — Read-only agent:

"rules": {
  "~/workspace/**":   "r--",
  "~/documents/**":   "r--",
  "/usr/bin/**":      "r-x"
},
"default": "---"

Example 3 — Locked-down agent with single writable scratch dir:

"rules": {
  "~/workspace/**":         "r--",
  "~/workspace/scratch/**": "rwx",
  "/usr/bin/**":            "r-x",
  "/usr/bin/curl":          "---",
  "/usr/bin/wget":          "---"
},
"deny": ["~/.openclaw/**", "~/.ssh/**", "~/.gnupg/**"],
"default": "---"

Precedence:

  1. deny list — always blocks, no override
  2. Most specific rules match — longest glob wins
  3. Wildcard rules match — fallback within rules
  4. default — catch-all (recommend ---)

Related: #12202, #513, #9348, #7284

Additional information

The path extraction approach prototyped in #12202 for file tools could be reused here for
the exec surface. The key extension is evaluating the extracted paths against the RWX
permission map rather than a simple allowlist/denylist.

Must remain backward-compatible with existing exec allowlist config keys.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal backlog priority with limited blast radius.clawsweeper:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:needs-security-reviewClawSweeper marked this issue as needing security-sensitive review.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.enhancementNew feature or requestimpact:securitySecurity boundary, credential, authz, sandbox, or sensitive-data risk.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions