OpenClaw 多机器人安全审计
审计任何 OpenClaw Telegram 机器人以发现多租户安全问题。基于部署多个 OpenClaw Telegram 机器人时发生的真实生产事故。
何时使用:
- 在发布公共 OpenClaw Telegram 机器人之前
- 在现有机器人添加多用户支持后
- 在审查任何为多个用户提供服务的 OpenClaw 网关的安全性时
- 当您怀疑跨用户数据泄露时
关键背景:OpenClaw 的安全模型
从官方文档(https://docs.openclaw.ai/gateway/security)中:
"OpenClaw 不是多个对抗性用户共享一个代理/网关的敌对多租户安全边界。"
"如果您需要混合信任或对抗性用户操作,请分离信任边界(单独网关 + 凭证,理想情况下单独的操作系统用户/主机)。"
任何公共 Telegram 机器人(dmPolicy: "open", allowFrom: [""])都是混合信任场景。请相应地进行规划。
审计清单:
逐一检查每个项目。标记为 PASS、FAIL 或 N/A。
文件:config/openclaw.json
[ ] session.dmScope 为 "per-channel-peer"(或 "per-account-channel-peer")
没有这一点:所有用户共享相同的对话上下文。Alice 的私人消息泄露给 Bob。
// 正确 "session": { "dmScope": "per-channel-peer" }
// 错误(或缺失)"session": {}文件:provision-user.sh 或 openclaw.json
[ ] tools.fs.workspaceOnly 为每个用户代理设置为 true
没有这一点:代理可以读取/写入/编辑系统上的任何文件。用户 A 可以通过文件系统工具读取 /workspaces/B/USER.md。
每个代理配置(在 provision-user.sh 中设置):
agent_entry["tools"] = {"fs": {"workspaceOnly": True}}
agent_entry["tools"]["exec"] = {"applyPatch": {"workspaceOnly": True}}
重要:workspaceOnly 只阻止读取/写入/编辑/应用补丁。它不阻止 exec shell 命令。代理仍然可以执行 cat /workspaces/other_user/。[ ] sandbox.mode 为 "all",范围为 "agent" 或 "session"
没有这一点:exec 命令在主机上运行,具有完整的文件系统访问权限。这是真正防止基于 shell 的跨用户访问的唯一方法。
// 完整的容器隔离(资源密集 - 每个代理一个 Docker 容器)
{ "agents": { "list": [{ "id": "user-123", "workspace": "/workspaces/123", "sandbox": { "mode": "all", "scope": "agent", "workspaceAccess": "rw" } }] } }
权衡:每个代理一个容器 = 每个用户 ~50-100MB RAM。对于少于 50 个用户,接受。对于 500+,昂贵。实际替代方案(如果没有 sandbox):接受缺口,依赖 SOUL.md + message-guard hook,记录限制。文件:provision-user.sh、entrypoint.sh
[ ] provision-user.sh 从主代理复制 auth-profiles.json 到用户代理
[ ] entrypoint.sh 在容器重启时重新复制 auth-profiles.json
没有这一点:用户代理在重启后无法发送消息。静默失败。
# 在 provision-user.sh 中(在 openclaw 代理添加后):
MAIN_AUTH="/root/.openclaw-PROFILE/agents/main/agent/auth-profiles.json"
AGENT_AUTH_DIR="/root/.openclaw-PROFILE/agents/user-${UID}/agent"
mkdir -p "${AGENT_AUTH_DIR}"
cp "${MAIN_AUTH}" "${AGENT_AUTH_DIR}/auth-profiles.json"
# 在 entrypoint.sh 中(在代理重新注册循环后):
for uid_dir in /workspaces/[0-9]; do
uid=$(basename "$uid_dir")
agent_auth_dir="/root/.openclaw-PROFILE/agents/user-${uid}/agent"
if [ ! -f "${agent_auth_dir}/auth-profiles.json" ]; then
mkdir -p "${agent_auth_dir}"
cp "${MAIN_AUTH}" "${agent_auth_dir}/auth-profiles.json"
fi
done
文件:entrypoint.sh
[ ] workspaceOnly 设置在 entrypoint 重新注册代理后重新应用
没有这一点:openclaw 代理添加可能会覆盖工具配置,丢失隔离。
绑定恢复 Python 块后,重新应用:
for uid, info in reg.get("users", {}).items():
aid = info.get("agent_id", f"user-{uid}")
for entry in config.get("agents", {}).get("list", []):
if entry.get("id") == aid:
entry.setdefault("tools", {})
entry["tools"]["fs"] = {"workspaceOnly": True}
entry["tools"].setdefault("exec", {})["applyPatch"] = {"workspaceOnly": True}
break
文件:provision-user.sh
[ ] Telegram 用户 ID 验证为仅数字
没有这一点:通过 user_id=../../etc/passwd 进行路径遍历
if ! [[ "${TELEGRAM_USER_ID}" =~ ^[0-9]+$ ]]; then
echo "ERROR: TELEGRAM_USER_ID 必须是数字" >&2
exit 1
fi
文件:provision-user.sh
[ ] 用户工作空间创建时具有 chmod 700
没有这一点:容器中的其他进程可以读取用户数据。
mkdir -p "${USER_DIR}"/{memory,output,data}
chmod 700 "${USER_DIR}"
文件:provision-user.sh
[ ] 使用 flock 防止并发预配竞争
[ ] 幂等检查(如果已经预配,则跳过)
没有这一点:同一用户的两条消息可能会创建...