What each agent tool can actually enforce

Shared by Pavel · Updated 2026-11-06

Direct answer: Enforced by the harness: OS sandboxes, permission deny rules, and blocking hooks. Advisory: instruction files such as CLAUDE.md, Cursor rules, and Cursor's Auto-review hints. Sandboxes cover shell commands, not every tool.

Rule of thumb: put what must never happen into a deny rule, hook or sandbox, and what should usually happen into text.

Label key: [vendor] = vendor documentation; [measured] = a number measured (vendor-run unless said); [opinion] = judgment. All sources read 2026-11-06.

Table

ToolEnforced by the harnessAdvisory or best-effort
Claude CodePermission deny/ask rules; PreToolUse hook exit 2 blocks; optional OS sandbox for shell commands (off by default)CLAUDE.md ("context, not enforced configuration"); Read deny on Grep/Glob is "best-effort"
CodexOS-enforced sandbox (default: no network, writes limited to workspace); .git, .codex, .agents, .aws read-only in writable rootsApproval policy only gates what the sandbox lets through; web search is outside the command proxy
CursorSandbox for terminal commands when used; hooks (exit 2 blocks); protected pathsAuto-review classifier ("not a security boundary"); .cursorignore ("complete protection isn't guaranteed"); rules
OpenClawTool allow/deny, sandbox mode, workspace access ro/noneModel choice is "first and cheapest layer", not hard enforcement

Sources [vendor]: Claude Code https://code.claude.com/docs/en/memory , https://code.claude.com/docs/en/permissions , https://code.claude.com/docs/en/sandboxing ; Codex https://developers.openai.com/codex/agent-approvals-security ; Cursor https://cursor.com/docs/agent/security/run-modes , https://cursor.com/docs/reference/permissions , https://cursor.com/docs/reference/ignore-file , https://cursor.com/docs/hooks ; OpenClaw https://docs.openclaw.ai/gateway/security/tool-permissions , https://docs.openclaw.ai/gateway/security/prompt-injection .

What each cannot do [vendor]

Prompt injection: reader and actor split

Vendor statements:

Setup: Reader agent: no write, exec or send tools, reads mail and web, returns a fixed JSON schema. Actor agent: has tools, reads only that JSON, never the raw text. Limits: free-text fields in the JSON still carry injections; the harness cannot check meaning.

Starter configs (all not yet tested)

Claude Code reader (.claude/settings.json; key names from the permissions and sandboxing pages):

{
  "permissions": {
    "deny": ["Bash", "Edit", "Write", "Read(./.env)", "Read(./secrets/**)"],
    "allow": ["WebFetch(domain:docs.example.com)"]
  },
  "sandbox": { "enabled": true }
}

A bare Bash deny removes the tool from context [vendor, permissions page]. For the actor add a hook; exit 2 blocks the call.

Codex reader (~/.codex/config.toml):

sandbox_mode = "read-only"
approval_policy = "on-request"
web_search = "cached"

Run codex --sandbox read-only --ask-for-approval on-request for the same effect.

Cursor reader (.cursor/sandbox.json, .cursorignore):

{ "type": "workspace_readonly", "networkPolicy": { "default": "deny", "allow": [] } }

.cursorignore: .env and secrets/. Actor hook, .cursor/hooks.json (not yet tested):

{"version":1,"hooks":{"beforeShellExecution":[{"command":"./check.sh","failClosed":true}]}}

OpenClaw reader (openclaw.json, adapted from the tool-permissions page):

{ agents: { entries: { reader: {
  sandbox: { mode: "all", scope: "agent", workspaceAccess: "none" },
  tools: { allow: ["read"], deny: ["write","edit","apply_patch","exec","process","browser","gateway","cron","sessions_spawn","sessions_send"] }
} } } }

Note the page's read-only example allows read with workspaceAccess ro; with none there may be nothing to read. Adjust to your case.

Gaps