Tool Policies: Allow/Deny Rules, Three-Level Sandbox Config and Elevated Flag
Chapter 15: Tool Policy โ Allow/Deny Rules, Three-Level Sandbox Configuration, and the elevated Flag
Overview
OpenClaw's tool policy system is the core of the entire security architecture. It uses Allow/Deny rules to control which tools can be used, sandboxes to control the isolation level of code execution, and the elevated flag to allow specific trusted commands to bypass sandbox restrictions. Understanding this mechanism is key to finding the right balance between security and productivity.
15.1 deny > allow Priority Rules
Core Design Principle
OpenClaw's tool policy follows a security-first design:
global deny > global allow > per-agent allow > per-agent deny
Specifically:
- Global deny has the highest weight โ globally denied tools are never available regardless of any Agent config
- Global allow provides the baseline set of available tools for all Agents
- Per-agent allow adds permissions for specific Agents on top of the global baseline
- Per-agent deny adds additional restrictions for specific Agents on top of the global baseline
Security Significance
The security significance of this design is: administrators can set unbreakable security boundaries through global deny. Even if an Agent's configuration is maliciously tampered with (Prompt Injection), attackers cannot bypass global deny to access forbidden tools.
Attacker attempts to enable exec via Prompt Injection
|
v
per-agent config adds exec allow
|
v
System checks global policy: exec is in global deny list
|
v
Request denied โ Prompt Injection ineffective
15.2 Global Tool Policy Configuration
Basic Configuration Format
{
"tool_policy": {
"global": {
"deny": [
"exec",
"bash",
"process",
"node_*"
],
"allow": [
"read",
"write",
"edit",
"web_search",
"message",
"memory_search",
"memory_get"
]
}
}
}
Wildcard Support
{
"tool_policy": {
"global": {
"deny": [
"node_*", // Deny all tools with node_ prefix
"canvas_*" // Deny all tools with canvas_ prefix
],
"allow": [
"*" // Allow all tools not denied
]
}
}
}
Principle of Least Privilege (Recommended Production Configuration)
{
"tool_policy": {
"global": {
"deny": ["*"],
"allow": []
}
}
}
When global deny is ["*"], all tools are denied by default. Each Agent must explicitly request the tool permissions it needs.
15.3 Per-Agent Tool Exception Configuration
Inherit + Override Mechanism
{
"agents": {
"file-processor": {
"tool_policy": {
"inherit_global": true,
"allow": ["read", "write", "edit"],
"deny": ["exec", "bash"]
}
},
"code-executor": {
"tool_policy": {
"inherit_global": true,
"allow": ["read", "exec", "bash"],
"deny": ["browser", "web_search"]
}
},
"web-scraper": {
"tool_policy": {
"inherit_global": true,
"allow": ["browser", "web_search", "write"],
"deny": ["exec", "bash", "process"]
}
}
}
}
Layered Application Example
Assume the global configuration is:
{
"global": {
"deny": ["process", "node_*"],
"allow": ["read", "write", "web_search"]
}
}
Derived tool availability for each Agent:
| Tool | Global Policy | file-processor | code-executor |
|---|---|---|---|
| read | allow | allow (inherited) | allow (inherited) |
| write | allow | allow (inherited) | -- |
| exec | not configured | deny (explicit) | allow (explicit) |
| bash | not configured | deny (explicit) | allow (explicit) |
| process | deny | deny (inherited) | deny (inherited, cannot override) |
| web_search | allow | -- | deny (explicit) |
| browser | not configured | -- | deny (explicit) |
Key point: The global deny on
processcannot be overridden by any per-agent configuration.
15.4 Three-Level Sandbox Configuration
Sandbox Levels
OpenClaw provides three sandbox execution levels:
off โโโโโโโบ Host direct execution, no isolation
non-main โโโบ Main Agent on host, sub-Agents in containers
all โโโโโโโโบ All Agents (including main Agent) run in containers
Level 1: off (No Sandbox)
{
"sandbox": {
"level": "off"
}
}
Applicable scenarios:
- Local development environments with fully trusted operations
- Scenarios requiring access to host resources (GPU, hardware devices)
- Where performance requirements are extreme and containerization overhead is unacceptable
Risk: exec/bash commands run directly on the host โ file system damage risk exists.
Level 2: non-main (Secondary Sandbox)
{
"sandbox": {
"level": "non-main",
"container_backend": "docker",
"image": "openclaw/agent-sandbox:latest"
}
}
Execution model:
Main Agent (host execution)
|
+--> sessions_spawn --> Sub-Agent (container execution)
| |
| +--> exec (inside container)
| +--> bash (inside container)
|
+--> exec (on host) โ ๏ธ Note: not isolated
Applicable scenarios:
- Main Agent needs access to host resources
- Sub-Agents spawned by the main Agent need isolation
Level 3: all (Full Sandbox)
{
"sandbox": {
"level": "all",
"container_backend": "docker",
"image": "openclaw/agent-sandbox:latest",
"resource_limits": {
"cpu": "2",
"memory": "4g",
"disk": "10g",
"network": "limited"
}
}
}
Applicable scenarios:
- Processing untrusted code or user input
- Multi-tenant scenarios requiring strict isolation
- Security compliance mandating strong isolation
Execution model:
Main Agent (runs in Container A)
|
+--> exec (inside Container A) โ Isolated
+--> bash (inside Container A) โ Isolated
|
+--> sessions_spawn --> Sub-Agent (runs in Container B) โ Double isolated
Three-Level Sandbox Comparison
| Dimension | off | non-main | all |
|---|---|---|---|
| Main Agent exec isolated | No | No | Yes |
| Sub-Agent exec isolated | No | Yes | Yes |
| Performance overhead | Lowest | Medium | Highest |
| Host resource access | Full | Main Agent only | Restricted |
| Applicable security level | Low | Medium | High |
| Production recommended | No | Yes (controlled) | Yes (untrusted input) |
15.5 Three Sandbox Scope Isolation Granularities
Sandbox Scope controls the sharing/isolation range of containers:
{
"sandbox": {
"level": "all",
"scope": "session"
}
}
session scope (Session Isolation)
User Session A --> [Dedicated Container A]
User Session B --> [Dedicated Container B]
(Completely isolated between sessions)
Applicable scenario: Multiple users using simultaneously, each user's operations independent.
agent scope (Agent Isolation)
Session A:
Main Agent --> [Container A1]
Sub-Agent 1 --> [Container A2]
Sub-Agent 2 --> [Container A3]
(Different Agents within the same session are isolated from each other)
Applicable scenario: High-security scenarios, preventing sub-Agents from interfering with each other.
shared scope (Shared Container)
Main Agent โโโ
Sub-Agent 1 โโโโบ [Shared Container]
Sub-Agent 2 โโโ
(All Agents in the same session share one container)
Applicable scenario: Collaborative scenarios where Agents need to share filesystem and processes.
Scope Comparison
| Scope | Isolation Level | Performance | Applicable Scenario |
|---|---|---|---|
session |
Inter-session isolation | Medium | Multi-user services |
agent |
Inter-Agent isolation | Low (most containers) | High security needs |
shared |
Same-session sharing | High (fewest containers) | Collaborative multi-Agent |
15.6 Three Sandbox Backend Options
Docker Backend (Recommended)
{
"sandbox": {
"backend": "docker",
"docker": {
"image": "openclaw/agent-sandbox:3.0",
"pull_policy": "if-not-present",
"network_mode": "bridge",
"volumes": [
{
"host": "/workspace",
"container": "/workspace",
"mode": "rw"
}
],
"env": {
"PYTHONPATH": "/workspace"
}
}
}
}
Advantages:
- Standardized, cross-platform
- Rich image ecosystem
- Fine-grained resource limits
- Strong network isolation capability
SSH Backend (Remote Execution)
{
"sandbox": {
"backend": "ssh",
"ssh": {
"host": "sandbox.internal.company.com",
"port": 22,
"user": "agent",
"key_file": "/etc/openclaw/agent_ssh_key",
"known_hosts": "/etc/openclaw/known_hosts"
}
}
}
Applicable scenarios:
- Executing commands on dedicated secure servers
- Accessing specific network environments (e.g., production database servers)
- Remote servers with specific hardware resources needed
OpenShell Backend (Lightweight Isolation)
{
"sandbox": {
"backend": "openshell",
"openshell": {
"namespace": "agent-ns",
"user": "nobody",
"chroot": "/var/openclaw/chroot"
}
}
}
Applicable scenarios:
- Environments where Docker is not supported (e.g., some embedded systems)
- Need more isolation than bare-metal execution but cannot use containers
- Lightweight sandbox requirements
Three Backend Comparison
| Backend | Isolation Strength | Startup Speed | Resource Overhead | Applicable Scenario |
|---|---|---|---|---|
| Docker | Strong | Medium (seconds) | Medium | General production environments |
| SSH | Medium (depends on remote) | Slow (connection setup) | Low (local) | Remote secure execution |
| OpenShell | Weak | Fast (milliseconds) | Minimal | Embedded/lightweight |
15.7 The elevated Flag
Purpose
The elevated flag allows specific commands or tool calls to bypass the sandbox's filesystem and network restrictions, but does not bypass tool policy.
Important distinction:
- elevated can let commands access paths outside the sandbox
- elevated cannot make denied tools become available
Configuration
{
"tools": {
"exec": {
"elevated_commands": [
{
"pattern": "docker build *",
"reason": "Needs access to Docker socket"
},
{
"pattern": "systemctl reload nginx",
"reason": "Reload Nginx configuration"
}
]
}
}
}
elevated Usage Example
{
"tool": "exec",
"input": {
"command": "docker build -t myapp:latest /workspace",
"elevated": true
}
}
Risks of elevated
| Risk | Description | Mitigation |
|---|---|---|
| Host filesystem access | Can read/write paths outside the sandbox | Use pattern allowlist to restrict commands |
| Privilege escalation | Executing commands with elevated permissions | Pair with SSH backend to limit user permissions |
| Audit difficulty | elevated operations are harder to track | Enable elevated operation logging |
elevated Best Practices
{
"tools": {
"exec": {
"elevated_commands": [
{
"pattern": "^docker (build|push|pull) [a-zA-Z0-9/_:-]+$",
"reason": "CI/CD Docker operations",
"audit_log": true,
"require_approval": false
}
],
"elevated_audit_log": "/var/log/openclaw/elevated.log"
}
}
}
15.8 Dangerous Environment Variable Stripping
Variables That Are Stripped
Before executing exec or bash, OpenClaw automatically strips the following dangerous environment variables:
DYLD_INSERT_LIBRARIES // macOS dynamic library injection
DYLD_LIBRARY_PATH // macOS dynamic library path hijacking
DYLD_FRAMEWORK_PATH // macOS framework path hijacking
LD_PRELOAD // Linux shared library preloading
LD_LIBRARY_PATH // Linux library path
NODE_OPTIONS // Node.js option injection (can execute arbitrary code)
PYTHONSTARTUP // Python startup script injection
PERL5OPT // Perl option injection
RUBYOPT // Ruby option injection
Why These Variables Are Dangerous
# Attack example: using NODE_OPTIONS to execute arbitrary code in any Node.js process
export NODE_OPTIONS="--require /tmp/malicious.js"
node legitimate-script.js
# malicious.js is loaded before legitimate-script.js executes
# OpenClaw removes NODE_OPTIONS before execution
# Even if the Agent was injected with this variable, it has no effect
Custom Stripping Rules
{
"security": {
"strip_env_vars": {
"builtin": true,
"custom_patterns": [
"SECRET_*",
"INTERNAL_*",
"AWS_SECRET_*"
]
}
}
}
15.9 Least Privilege Principle: Practical Configuration Examples
Scenario 1: Pure Document Processing Agent
{
"agent": {
"name": "doc-processor",
"tool_policy": {
"allow": ["read", "write", "edit", "memory_search"],
"deny": ["exec", "bash", "process", "browser", "web_search"]
},
"sandbox": {
"level": "off"
},
"allowed_paths": ["/workspace/docs/**", "/output/**"]
}
}
Scenario 2: Controlled Code Execution Agent
{
"agent": {
"name": "code-runner",
"tool_policy": {
"allow": ["read", "exec", "bash", "message"],
"deny": ["write", "browser", "process", "web_search"]
},
"sandbox": {
"level": "all",
"backend": "docker",
"scope": "agent",
"docker": {
"image": "python:3.12-slim",
"network_mode": "none",
"resource_limits": {
"cpu": "1",
"memory": "512m"
}
}
}
}
}
Scenario 3: Web Crawler Agent (High Isolation)
{
"agent": {
"name": "web-crawler",
"tool_policy": {
"allow": ["browser", "web_search", "write", "message"],
"deny": ["exec", "bash", "process", "read", "edit"]
},
"sandbox": {
"level": "all",
"backend": "docker",
"scope": "session",
"docker": {
"image": "openclaw/browser-sandbox:latest",
"network_mode": "bridge",
"resource_limits": {
"cpu": "2",
"memory": "2g"
}
}
}
}
}
Scenario 4: Multi-Tenant SaaS Platform Configuration
{
"tool_policy": {
"global": {
"deny": ["process", "node_*", "canvas_*"],
"allow": []
}
},
"sandbox": {
"level": "all",
"backend": "docker",
"scope": "session",
"image": "openclaw/agent-sandbox:latest"
},
"security": {
"strip_env_vars": {
"builtin": true,
"custom_patterns": ["TENANT_SECRET_*", "INTERNAL_*"]
},
"audit_log": {
"enabled": true,
"path": "/var/log/openclaw/audit.log",
"include_tool_inputs": false
}
}
}
15.10 Tool Policy Auditing and Monitoring
Enabling Audit Logging
{
"security": {
"audit": {
"enabled": true,
"log_path": "/var/log/openclaw/tool_audit.log",
"log_level": "info",
"include": {
"tool_calls": true,
"tool_denials": true,
"elevated_calls": true,
"sandbox_violations": true
}
}
}
}
Audit Log Format
{
"timestamp": "2026-04-26T10:23:41Z",
"agent": "code-runner",
"session": "sess_abc123",
"event": "tool_denied",
"tool": "process",
"reason": "global_deny_policy",
"input_summary": "action=start, command=malicious-cmd"
}
Real-Time Monitoring Commands
# Monitor tool denial events
openclaw monitor --event tool_denied --tail
# View elevated operation history
openclaw audit --filter elevated --since 24h
# Export security report
openclaw audit --format json --output security-report.json
15.11 Complete Policy Inheritance Tree Example
Global Policy
โโโ deny: [process, node_*]
โโโ allow: [read, write, web_search]
โ
โโโ Agent: customer-service
โ โโโ Inherits global allow
โ โโโ Extra allow: [message, memory_search]
โ โโโ Extra deny: [exec, bash, browser]
โ
โโโ Agent: data-analyst
โ โโโ Inherits global allow
โ โโโ Extra allow: [exec, bash, memory_search]
โ โโโ Extra deny: [browser]
โ
โโโ Agent: web-scraper
โโโ Inherits global allow
โโโ Extra allow: [browser]
โโโ Extra deny: [exec, bash, process]
(process already in global deny; redundant declaration has no effect)
Chapter Summary
- deny > allow priority is the foundation of security boundaries: global deny cannot be broken by any Agent configuration
- Per-agent exceptions use an inherit+override mechanism for fine-grained control on top of global policy
- Three sandbox levels (off/non-main/all) cover all scenarios from development to production
- Three Scopes (session/agent/shared) control container isolation granularity
- Three backends (Docker/SSH/OpenShell) adapt to different infrastructure environments
- The elevated flag allows bypassing sandbox filesystem restrictions but not tool policy โ use with caution
- Dangerous environment variable stripping is an important defense against supply chain attacks and injection attacks
- The principle of least privilege should permeate all Agent configurations: start with global deny all, then grant permissions as needed
Through the tool policy system in this chapter, you can build OpenClaw Agent deployments that are both flexible and secure, finding the optimal balance between productivity and security.