拓冰建站拓冰建站
首页 / 资讯中心 / 正文

从零实现 OpenClaw (09):安全沙箱与权限管理 —— 用 Docker 给智能体戴上“理性的枷锁”并接入 TaoToken

1. 为什么智能体必须戴上“理性的枷锁”OpenClaw 这类智能体一旦能执行代码、读写文件、调用外部接口风险就不再是“回答错一句话”这么简单。我见过最典型的翻车路径你让它清理临时文件它推理出“占用空间且非核心数据”的目录还包括~/.ssh和/etc然后带着宿主机权限执行删除。逻辑上它没错后果上你崩溃。所以安全沙箱与权限管理要解决的核心问题是不信任 Agent 产生的任何原始指令。所有外部交互必须经过“隔离执行 权限校验”两层关卡。隔离执行负责把破坏半径压到一个生命周期极短的容器里权限校验负责在指令进入容器之前就判断它是否越界。这套方案适合谁适合已经把 OpenClaw 跑起来、开始接真实文件系统和硬件、但还没做执行隔离的开发者。你需要有 Docker 基础能看懂config.toml会用命令行拉取镜像和查看容器日志。本文给出可直接复制的 Dockerfile、config.toml与权限策略骨架并演示通过统一 Key/API 通道接入 TaoToken 后的验证动作与预期结果。2. TaoToken 前置统一 Key 与 API 通道在讲沙箱之前先把模型调用这条链路理清楚。OpenClaw 的“语义过滤层”和“权限校验器”本身也需要调用大模型来判断指令意图如果每个组件各自维护一套 Key权限边界会变得非常混乱。我的做法是所有模型请求统一走 TaoToken 的 API 通道用一套 Key 管理。TaoToken 官网地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基址是 https://taotoken.net/api 。注意 API 地址不带 UTM 参数直接写进配置即可。你需要先拿到 Key。进入控制台创建 API Key地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content Key 管理页在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。创建后复制那串sk-开头的字符串后面写进config.toml的环境变量引用里不要硬编码进代码。如果你只是想先验证模型通道是否通可以用模型对话页面直接发一条测试消息 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。这一步不涉及沙箱纯粹确认 Key 有效、网络可达。对于长期跑编码任务或 Agent 循环的场景建议了解 Coding Plan https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 里面有各语言 SDK 的调用示例。3. 可复制配置Dockerfile、config.toml 与权限策略3.1 沙箱镜像 Dockerfile沙箱镜像的原则是“够用就好”不要装编译器、不要装包管理器缓存、不要留 shell 历史。下面这个 Dockerfile 基于 Alpine只保留 Python 运行时和最小依赖。FROM python:3.10-alpine # 创建非 root 用户容器内也不给 root RUN addgroup -S claw adduser -S claw -G claw # 只装运行必需的库不装 build-base RUN apk add --no-cache libstdc WORKDIR /sandbox # 拷贝一个极简的入口脚本 COPY entrypoint.py /sandbox/entrypoint.py RUN chown -R claw:claw /sandbox USER claw ENTRYPOINT [python3, /sandbox/entrypoint.py]entrypoint.py负责从环境变量读取待执行代码执行后立即退出import os import sys code os.environ.get(CLAW_CODE, ) if not code: print(no code provided, filesys.stderr) sys.exit(1) try: exec(code, {__name__: __main__}) except Exception as e: print(fexecution error: {e}, filesys.stderr) sys.exit(2)构建命令docker build -t claw-sandbox:latest -f Dockerfile.sandbox .3.2 config.toml 沙箱与权限段OpenClaw 的config.toml里新增[sandbox]和[permission]两段。注意api_key用环境变量引用不要写明文。[llm] provider taotoken base_url https://taotoken.net/api api_key ${TAOTOKEN_API_KEY} model claude-3-5-sonnet [sandbox] enabled true image claw-sandbox:latest mem_limit 512m cpu_quota 50000 # 0.5 CPU单位是 1/100000 network_disabled true timeout_seconds 10 read_only_rootfs true tmpfs_size 64m [permission] manifest_path ./PERMISSIONS.md hitl_risk_threshold 0.7 audit_log ./logs/permission_audit.lognetwork_disabled true是关键默认切断沙箱网络只有显式在权限清单里放行的域名才通过代理白名单访问。read_only_rootfs true让容器根文件系统只读写操作只能落到 tmpfs 或挂载的卷。3.3 PERMISSIONS.md 权限策略骨架权限清单用 Markdown 写方便人和模型同时阅读。下面是一个可直接改用的骨架# OpenClaw Permission Manifest ## FileSystem - READ: /home/user/workspace/data/ - WRITE: /home/user/workspace/output/ - FORBIDDEN: /etc/, ~/.ssh/, ~/.env, /var/lib/ ## Network - ALLOW: api.taotoken.net, arxiv.org - DENY: * ## Hardware_Arm - MAX_SPEED: 0.5 rad/s - FORBIDDEN_ZONE: x 0, y 0, z 10 ## Risk - HITL_REQUIRED: delete_database, modify_system_config, arm_move_large解析逻辑放在PermissionGuard里核心是前缀匹配和风险评分class PermissionGuard: def __init__(self, manifest_path: str): self.manifest self._parse(manifest_path) def validate_action(self, skill_name: str, params: dict) - bool: if path in params: for forbidden in self.manifest[forbidden_paths]: if params[path].startswith(forbidden): return False if skill_name in self.manifest[hitl_required]: return self._request_human_approval(skill_name, params) return True4. 验证请求与成功结果配置写完后先做一次“越权拦截”验证再做一次“正常执行”验证。4.1 越权拦截验证构造一条试图写/etc/passwd的指令观察是否被PermissionGuard拦截python3 -c from permission_guard import PermissionGuard g PermissionGuard(./PERMISSIONS.md) print(g.validate_action(write_file, {path: /etc/passwd})) 预期输出False同时logs/permission_audit.log里应出现一条拒绝记录包含时间戳、skill 名、参数和拒绝原因。4.2 沙箱内正常执行验证构造一条在沙箱内做简单计算的指令确认容器能拉起、执行、返回python3 -c from claw_sandbox import ClawSandbox s ClawSandbox() r s.run_code(print(sum(range(100)))) print(r) 预期输出类似{status: success, output: 4950\n}4.3 模型通道验证用 TaoToken 的 API 发一条最小请求确认 Key 和 base_url 正确curl -s https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -H Content-Type: application/json \ -d {model:claude-3-5-sonnet,messages:[{role:user,content:ping}]}预期返回 JSON 里包含choices字段和模型回复内容。如果返回 401检查 Key 是否复制完整如果返回 404检查 base_url 是否写成了带路径的完整地址。5. 本篇常见错排查容器起不来报permission denied检查 Dockerfile 里USER claw是否在chown之后。如果先切用户再 chown非 root 用户没有权限改文件属主。沙箱内代码执行超时timeout_seconds默认 10 秒复杂计算会被截断。调大这个值的同时记得同步调大mem_limit否则 OOM 会先触发。网络白名单不生效network_disabled true时容器默认无网络。白名单放行需要配合一个正向代理容器在config.toml里配置proxy_url。如果只写了 ALLOW 但没配代理请求会直接失败。权限清单解析报错PERMISSIONS.md的缩进和冒号格式要严格。FORBIDDEN:后面跟路径列表用逗号分隔不要用换行。解析器对空行敏感建议用yaml.safe_load前先做一次格式清洗。HITL 审批不触发检查hitl_risk_threshold是否设得过高。风险评分是 0 到 1 的浮点数阈值 0.7 意味着只有高风险操作才触发人工确认。如果所有操作都触发把阈值调到 0.9。审计日志不写入audit_log路径的父目录必须存在。OpenClaw 不会自动创建目录需要手动mkdir -p logs。6. 接入与排障入口沙箱和权限配置跑通后模型调用这条链路建议统一收口到 TaoToken。排障和接入相关的操作直接走 API Keys 页面和接入文档API Keys 管理 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content接入文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content验证模型是否可用用模型对话页面发一条测试消息即可 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content如果你打算让 OpenClaw 长期跑编码任务或 Agent 循环Coding Plan 的配额和稳定性更适合这种场景 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content最后提醒一句沙箱不是万能的。read_only_rootfs和network_disabled能挡住大部分误操作但挡不住模型通过合法路径做慢速数据渗出。权限清单要定期 review尤其是 WRITE 目录的范围别为了省事写成/home/user/。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门