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
| Tool | Enforced by the harness | Advisory or best-effort |
|---|---|---|
| Claude Code | Permission 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" |
| Codex | OS-enforced sandbox (default: no network, writes limited to workspace); .git, .codex, .agents, .aws read-only in writable roots | Approval policy only gates what the sandbox lets through; web search is outside the command proxy |
| Cursor | Sandbox for terminal commands when used; hooks (exit 2 blocks); protected paths | Auto-review classifier ("not a security boundary"); .cursorignore ("complete protection isn't guaranteed"); rules |
| OpenClaw | Tool allow/deny, sandbox mode, workspace access ro/none | Model 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]
- Claude Code: The sandbox wraps shell commands only; Read, Edit, WebFetch and hooks run outside it, and
allowedDomainsdoes not limit WebFetch. A Bash deny rule matches the command as written, not the same program via another path. - Codex: The network proxy does not filter web search, connectors, MCP, browser tools or the client's model requests. Its DNS-rebinding check "does not eliminate" the risk.
- Cursor:
.cursorignoredoes not block the terminal or MCP tools. Hooks are fail-open by default: other non-zero exit codes let the action proceed unlessfailClosedis true. - OpenClaw: Plugins and skill folders run as trusted code. Agent-to-agent messaging is on by default. A cross-provider message setting defaults to allowed.
Prompt injection: reader and actor split
Vendor statements:
- OpenClaw [vendor]: "using a read-only or tool-disabled reader agent to summarize untrusted content, then pass the summary to your main agent." It adds that the summary "remains untrusted" and send-only access does not stop the recipient from executing an injected request. For Gmail, route untrusted mail to a dedicated reader agent.
- OpenAI [vendor]: extract only structured fields (enums, validated JSON) from external input; structured outputs "greatly reduce, but don't fully remove" the risk. https://developers.openai.com/api/docs/guides/agent-builder-safety (Agent Builder is scheduled to shut down 2026-11-30 per that page.)
- Meta [vendor]: an agent should have at most two of: untrusted input, sensitive data, ability to change state or communicate externally. https://ai.meta.com/blog/practical-ai-agent-security/
- Anthropic [vendor]: "No browser agent is immune to prompt injection." Its own adaptive attacker with 100 attempts per environment reached about 1% success on the latest model [measured, vendor-run]. https://www.anthropic.com/research/prompt-injection-defenses
- Simon Willison [opinion]: a quarantined model with no tools reads untrusted content; a privileged model never sees its unfiltered output. https://simonwillison.net/2023/Apr/25/dual-llm-pattern/
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
- I did not test any config, or confirm each key against a running tool.
- Cursor's
networkPolicyshape was read from its sandbox reference; thetypevalueworkspace_readonlyis listed there. - No source read measures how often reader/actor splits stop real attacks. Anthropic's number is its own internal test.
- Claude Code hook JSON and Cursor hook script bodies are not included.