8.4 KiB
NanoClaw 安全模型
信任模型
| 实体 | 信任级别 | 理由 |
|---|---|---|
| 主群组(Main group) | 受信任 | 私人自我聊天,管理员控制 |
| 非主群组(Non-main groups) | 不受信任 | 其他用户可能是恶意的 |
| 容器 agent(Container agents) | 沙箱化 | 隔离的执行环境 |
| 入站消息(Incoming messages) | 用户输入 | 潜在的 prompt 注入 |
安全边界
1. 容器隔离(主要边界)
Agent 在容器(轻量级 Linux VM)中执行,提供:
- 进程隔离 - 容器进程无法影响宿主机
- 文件系统隔离 - 只有显式挂载的目录可见
- 非 root 执行 - 以非特权
node用户(uid 1000)运行 - 临时容器 - 每次调用都是全新环境(
--rm)
这是主要的安全边界。不是依赖应用级权限检查,而是通过限制挂载的内容来缩小攻击面。
2. 挂载安全
外部白名单 - 挂载权限存储在 ~/.config/nanoclaw/mount-allowlist.json,该文件:
- 位于项目根目录之外
- 永远不会挂载到容器中
- 无法被 agent 修改
默认阻止模式:
.ssh, .gnupg, .aws, .azure, .gcloud, .kube, .docker,
credentials, .env, .netrc, .npmrc, id_rsa, id_ed25519,
private_key, .secret
保护措施:
- 验证前解析符号链接(防止目录遍历攻击)
- 容器路径验证(拒绝
..和绝对路径) nonMainReadOnly选项强制非主群组使用只读
只读项目根目录:
主群组的项目根目录以只读方式挂载。Agent 需要的可写路径(store、群组目录、IPC、.claude/)单独挂载。这防止 agent 修改宿主机应用代码(src/、dist/、package.json 等),否则下次重启时整个沙箱将被完全绕过。store/ 目录以读写方式挂载,以便主 agent 可以直接访问 SQLite 数据库。
3. Session 隔离
每个群组在 data/sessions/{group}/.claude/ 拥有隔离的 Claude session:
- 群组无法查看其他群组的对话历史
- Session 数据包含完整的消息历史和已读取的文件内容
- 防止跨群组信息泄露
4. IPC 授权
消息和任务操作根据群组身份进行验证:
| 操作 | 主群组 | 非主群组 |
|---|---|---|
| 向自己的聊天发送消息 | ✓ | ✓ |
| 向其他聊天发送消息 | ✓ | ✗ |
| 为自己安排定时任务 | ✓ | ✓ |
| 为其他群组安排定时任务 | ✓ | ✗ |
| 查看所有任务 | ✓ | 仅自己的 |
| 管理其他群组 | ✓ | ✗ |
5. 凭证隔离(OneCLI Agent Vault)
真实的 API 凭证永远不会进入容器。NanoClaw 使用 OneCLI 的 Agent Vault 来代理出站请求并在网关层面注入凭证。
工作原理:
- 凭证通过
onecli secrets create一次性注册,由 OneCLI 存储和管理 - 当 NanoClaw 启动容器时,调用
applyContainerConfig()将出站 HTTPS 路由通过 OneCLI 网关 - 网关按 host 和 path 匹配请求,注入真实凭证并转发
- Agent 无法发现真实凭证——不在环境变量、stdin、文件或
/proc中
按 agent 策略: 每个 NanoClaw 群组拥有自己的 OneCLI agent 身份。这允许按群组设置不同的凭证策略(例如,销售 agent vs. 支持 agent)。OneCLI 支持速率限制,基于时间的访问和审批流程正在规划中。
不挂载的内容:
- 渠道认证 session(
store/auth/)——仅宿主机 - 挂载白名单——外部存储,永不挂载
- 任何匹配阻止模式的凭证
.env在项目根目录挂载中被/dev/null遮蔽
权限对比
| 能力 | 主群组 | 非主群组 |
|---|---|---|
| 项目根目录访问 | /workspace/project(只读) |
无 |
| Store(SQLite DB) | /workspace/project/store(读写) |
无 |
| 群组目录 | /workspace/group(读写) |
/workspace/group(读写) |
| 全局记忆 | 通过项目隐式访问 | /workspace/global(只读) |
| 额外挂载 | 可配置 | 只读,除非允许 |
| 网络访问 | 无限制 | 无限制 |
| MCP 工具 | 全部 | 全部 |
安全架构图
┌──────────────────────────────────────────────────────────────────┐
│ 不受信任区域(UNTRUSTED ZONE) │
│ 入站消息(潜在恶意) │
└────────────────────────────────┬─────────────────────────────────┘
│
▼ 触发检查、输入转义
┌──────────────────────────────────────────────────────────────────┐
│ 宿主机进程(HOST PROCESS,受信任) │
│ • 消息路由 │
│ • IPC 授权 │
│ • 挂载验证(外部白名单) │
│ • 容器生命周期 │
│ • OneCLI Agent Vault(注入凭证,执行策略) │
└────────────────────────────────┬─────────────────────────────────┘
│
▼ 仅显式挂载,无 secrets
┌──────────────────────────────────────────────────────────────────┐
│ 容器(CONTAINER,隔离/沙箱化) │
│ • Agent 执行 │
│ • Bash 命令(沙箱内) │
│ • 文件操作(限于挂载范围) │
│ • API 调用通过 OneCLI Agent Vault 路由 │
│ • 环境变量或文件系统中无真实凭证 │
└──────────────────────────────────────────────────────────────────┘
供应链安全(pnpm)
NanoClaw 使用 pnpm,在 pnpm-workspace.yaml 中配置了两道供应链防护:
最低发布龄期
minimumReleaseAge: 4320(3 天)。pnpm 将拒绝解析发布不到 3 天的任何包版本。这可以防御仿冒包和被盗用的维护者账户——大多数恶意发布在 72 小时内会被检测并撤回。
将包排除在发布龄期门禁之外(minimumReleaseAgeExclude):
这种情况应很少发生。当零日修复或关键依赖需要立即更新时:
- 排除条目必须经人类维护者审查和批准
- 条目必须锁定被排除的确切版本——绝不能使用范围或通配符
minimumReleaseAgeExclude: some-package: "1.2.3" # 由 @user 批准, 2026-04-14 — CVE-XXXX-YYYY 修复 - 一旦该版本超过阈值(即 3 天后),应移除排除项
- 自动化 agent(Claude、CI 机器人)绝不能在没有人类签署的情况下添加排除项
构建脚本白名单
onlyBuiltDependencies 限制哪些包可以执行 install/postinstall 脚本。只有此列表中的包才被允许在 pnpm install 期间运行构建脚本。当前允许的包:
better-sqlite3— 编译原生 SQLite 绑定esbuild— 下载平台特定的二进制文件protobufjs— 生成 protobuf 绑定(Baileys/libsignal 使用)sharp— 下载平台特定的图像处理二进制文件
向此列表添加包需要人类批准——构建脚本以安装用户的权限执行任意代码。
.npmrc 安全网
.npmrc 文件包含 minReleaseAge=3d 作为后备。权威设置在 pnpm-workspace.yaml 中,但如果 npm 曾被直接调用(例如被不遵循 pnpm 的工具调用),.npmrc 提供纵深防御。