第 15 章

工具策略:Allow/Deny 规则、沙箱三级配置与 elevated 标志

第15章:工具策略——Allow/Deny 规则、沙箱三级配置与 elevated 标志

概述

OpenClaw 的工具策略系统是整个安全架构的核心。它通过 Allow/Deny 规则控制哪些工具可以被使用,通过沙箱控制代码执行的隔离级别,通过 elevated 标志允许受信任的特定命令绕过沙箱限制。理解这套机制,是在安全与生产力之间找到正确平衡的关键。


15.1 deny > allow 优先级规则

核心设计原则

OpenClaw 的工具策略遵循安全优先设计:

全局 deny > 全局 allow > per-agent allow > per-agent deny

具体而言:

安全意义

这一设计的安全意义在于:管理员可以通过全局 deny 设置不可突破的安全边界,即使某个 Agent 的配置被恶意篡改(Prompt Injection),攻击者也无法绕过全局 deny 来访问被禁止的工具。

攻击者尝试通过 Prompt Injection 启用 exec 工具
    |
    v
Agent 配置中 per-agent 添加了 exec allow
    |
    v
系统检查全局策略:exec 在全局 deny 列表中
    |
    v
请求被拒绝,Prompt Injection 无效

15.2 全局工具策略配置

基础配置格式

{
  "tool_policy": {
    "global": {
      "deny": [
        "exec",
        "bash",
        "process",
        "node_*"
      ],
      "allow": [
        "read",
        "write",
        "edit",
        "web_search",
        "message",
        "memory_search",
        "memory_get"
      ]
    }
  }
}

通配符支持

{
  "tool_policy": {
    "global": {
      "deny": [
        "node_*",      // 禁止所有 node_ 前缀的工具
        "canvas_*"     // 禁止所有 canvas_ 前缀的工具
      ],
      "allow": [
        "*"            // 允许所有未被 deny 的工具
      ]
    }
  }
}

最小权限原则(推荐生产配置)

{
  "tool_policy": {
    "global": {
      "deny": ["*"],
      "allow": []
    }
  }
}

当全局 deny 为 ["*"] 时,默认禁止所有工具,每个 Agent 必须显式申请所需工具权限。


15.3 Per-Agent 工具例外配置

继承 + 覆盖机制

{
  "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"]
      }
    }
  }
}

层级应用示例

假设全局配置为:

{
  "global": {
    "deny": ["process", "node_*"],
    "allow": ["read", "write", "web_search"]
  }
}

各 Agent 工具可用性推导:

工具 全局策略 file-processor code-executor
read allow allow(继承) allow(继承)
write allow allow(继承) --
exec 未配置 deny(显式) allow(显式)
bash 未配置 deny(显式) allow(显式)
process deny deny(继承) deny(继承,无法覆盖)
web_search allow -- deny(显式)
browser 未配置 -- deny(显式)

关键点:全局 deny 的 process 无法被任何 per-agent 配置覆盖。


15.4 沙箱三级配置

沙箱级别

OpenClaw 提供三种沙箱执行级别:

off ──────► 主机直接执行,无隔离
non-main ──► 主 Agent 在主机,子 Agent 在容器
all ───────► 全部 Agent(含主 Agent)在容器中运行

级别一:off(无沙箱)

{
  "sandbox": {
    "level": "off"
  }
}

适用场景

风险:Agent 的 exec/bash 命令直接在主机执行,存在文件系统破坏风险。

级别二:non-main(次级沙箱)

{
  "sandbox": {
    "level": "non-main",
    "container_backend": "docker",
    "image": "openclaw/agent-sandbox:latest"
  }
}

执行模型

主 Agent(主机执行)
    |
    +--> sessions_spawn --> 子 Agent(容器执行)
    |                           |
    |                           +--> exec(在容器内)
    |                           +--> bash(在容器内)
    |
    +--> exec(在主机上)⚠️ 注意

适用场景

级别三:all(全沙箱)

{
  "sandbox": {
    "level": "all",
    "container_backend": "docker",
    "image": "openclaw/agent-sandbox:latest",
    "resource_limits": {
      "cpu": "2",
      "memory": "4g",
      "disk": "10g",
      "network": "limited"
    }
  }
}

适用场景

执行模型

主 Agent(容器A中执行)
    |
    +--> exec(在容器A内)✓ 隔离
    +--> bash(在容器A内)✓ 隔离
    |
    +--> sessions_spawn --> 子 Agent(容器B中执行)✓ 双重隔离

三级沙箱对比

维度 off non-main all
主 Agent exec 隔离
子 Agent exec 隔离
性能开销 最低 中等 最高
主机资源访问 完全 主 Agent 可访问 受限
适用安全等级
生产推荐 是(受控场景) 是(不信任输入)

15.5 沙箱 Scope 三种隔离粒度

沙箱 Scope 控制容器的共享/隔离范围:

{
  "sandbox": {
    "level": "all",
    "scope": "session"
  }
}

session scope(会话隔离)

用户会话 A --> [独立容器 A]
用户会话 B --> [独立容器 B]
(会话间完全隔离)

适用场景:多用户同时使用,每个用户的操作互不影响。

agent scope(Agent 隔离)

会话 A:
    主 Agent --> [容器 A1]
    子 Agent 1 --> [容器 A2]
    子 Agent 2 --> [容器 A3]
(同一会话内不同 Agent 互相隔离)

适用场景:高安全性场景,防止子 Agent 之间互相干扰。

shared scope(共享容器)

主 Agent ─┐
子 Agent 1 ├──► [共享容器]
子 Agent 2 ─┘
(同一会话所有 Agent 共享一个容器)

适用场景:需要 Agent 间共享文件系统和进程的协作场景。

Scope 对比

Scope 隔离级别 性能 适用场景
session 会话间隔离 多用户服务
agent Agent 间隔离 低(最多容器) 高安全需求
shared 同会话共享 高(最少容器) 协作式多 Agent

15.6 沙箱后端三种选择

Docker 后端(推荐)

{
  "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"
      }
    }
  }
}

优势

SSH 后端(远程执行)

{
  "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"
    }
  }
}

适用场景

OpenShell 后端(轻量隔离)

{
  "sandbox": {
    "backend": "openshell",
    "openshell": {
      "namespace": "agent-ns",
      "user": "nobody",
      "chroot": "/var/openclaw/chroot"
    }
  }
}

适用场景

三种后端对比

后端 隔离强度 启动速度 资源开销 适用场景
Docker 中(秒级) 通用生产环境
SSH 中(依赖远端) 慢(连接建立) 低(本地) 远程安全执行
OpenShell 快(毫秒级) 极低 嵌入式/轻量

15.7 elevated 标志

作用

elevated 标志允许特定命令或工具调用绕过沙箱的文件系统和网络限制,但不绕过工具策略

重要区分

  • elevated 可以让命令访问沙箱外的路径
  • elevated 不能让被 deny 的工具变为可用

配置方式

{
  "tools": {
    "exec": {
      "elevated_commands": [
        {
          "pattern": "docker build *",
          "reason": "需要访问 Docker socket"
        },
        {
          "pattern": "systemctl reload nginx",
          "reason": "重载 Nginx 配置"
        }
      ]
    }
  }
}

elevated 使用示例

{
  "tool": "exec",
  "input": {
    "command": "docker build -t myapp:latest /workspace",
    "elevated": true
  }
}

elevated 的风险

风险 说明 缓解措施
主机文件系统访问 可读写沙箱外的路径 使用 pattern 白名单限制命令
权限提升 以较高权限执行命令 配合 SSH 后端限制用户权限
审计困难 elevated 操作难以追踪 启用 elevated 操作日志

elevated 最佳实践

{
  "tools": {
    "exec": {
      "elevated_commands": [
        {
          "pattern": "^docker (build|push|pull) [a-zA-Z0-9/_:-]+$",
          "reason": "CI/CD Docker 操作",
          "audit_log": true,
          "require_approval": false
        }
      ],
      "elevated_audit_log": "/var/log/openclaw/elevated.log"
    }
  }
}

15.8 危险环境变量剥离机制

被剥离的环境变量

在执行 exec 或 bash 之前,OpenClaw 自动剥离以下危险环境变量:

DYLD_INSERT_LIBRARIES    // macOS 动态库注入
DYLD_LIBRARY_PATH        // macOS 动态库路径劫持
DYLD_FRAMEWORK_PATH      // macOS 框架路径劫持
LD_PRELOAD               // Linux 共享库预加载
LD_LIBRARY_PATH          // Linux 库路径
NODE_OPTIONS             // Node.js 选项注入(可执行任意代码)
PYTHONSTARTUP            // Python 启动脚本注入
PERL5OPT                 // Perl 选项注入
RUBYOPT                  // Ruby 选项注入

为什么这些变量危险

# 攻击示例:通过 NODE_OPTIONS 在任何 Node.js 进程中执行任意代码
export NODE_OPTIONS="--require /tmp/malicious.js"
node legitimate-script.js
# 此时 malicious.js 会在 legitimate-script.js 执行前被加载

# OpenClaw 会在执行前删除 NODE_OPTIONS
# 即使 Agent 被注入了这个变量,它也不会生效

自定义剥离规则

{
  "security": {
    "strip_env_vars": {
      "builtin": true,
      "custom_patterns": [
        "SECRET_*",
        "INTERNAL_*",
        "AWS_SECRET_*"
      ]
    }
  }
}

15.9 最小权限原则实践配置示例

场景一:纯文档处理 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/**"]
  }
}

场景二:受控代码执行 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"
        }
      }
    }
  }
}

场景三:网络爬虫 Agent(高隔离)

{
  "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"
        }
      }
    }
  }
}

场景四:多租户 SaaS 平台配置

{
  "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 工具策略审计与监控

启用审计日志

{
  "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
      }
    }
  }
}

审计日志格式

{
  "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"
}

实时监控命令

# 监控工具拒绝事件
openclaw monitor --event tool_denied --tail

# 查看 elevated 操作历史
openclaw audit --filter elevated --since 24h

# 导出安全报告
openclaw audit --format json --output security-report.json

15.11 策略继承树完整示例

全局策略
├── deny: [process, node_*]
├── allow: [read, write, web_search]
│
├── Agent: customer-service
│   ├── 继承全局 allow
│   ├── 额外 allow: [message, memory_search]
│   └── 额外 deny: [exec, bash, browser]
│
├── Agent: data-analyst
│   ├── 继承全局 allow
│   ├── 额外 allow: [exec, bash, memory_search]
│   └── 额外 deny: [browser]
│
└── Agent: web-scraper
    ├── 继承全局 allow
    ├── 额外 allow: [browser]
    └── 额外 deny: [exec, bash, process]
        (process 已在全局 deny,重复声明不影响)

本章小结

通过本章的工具策略体系,你可以构建既灵活又安全的 OpenClaw Agent 部署,在生产力与安全性之间找到最佳平衡点。

本章评分
4.8  / 5  (20 评分)

💬 留言讨论