本地 AI 代理一旦获得 “写文件、起容器、调 API” 的能力,就等同于在开发者电脑里放了一位 7×24 的初级实习生。Goose 把这位实习生的合同开源了:Rust 写的核心,插件化的技能,任何 LLM 都能指挥。好处是 “写完即跑”,风险是 “跑错即毁”。本文把官方文档没细说的沙箱与权限模型拆开,给你一份可直接抄进 CI 的落地清单。
一、Goose 的权限边界长什么样?
官方把能力拆成三层:
- Agent Runtime(crates/goose):纯 Rust,负责对话状态、工具调用、插件生命周期。默认无系统调用权限,所有 “动手” 动作必须落进插件。
- Extension(插件):独立进程,通过 MCP(Model Context Protocol)与 Runtime 通信。插件可以声明自己需要哪些 “能力”(capabilities),Runtime 只做白名单校验。
- MCP Server:把能力翻译成具体协议,例如 filesystem、docker、github。Server 本身可以用任意语言实现,Goose 仓库里提供了 Go、Python、TypeScript 三套模板。
一句话:Runtime 不直接碰系统,插件想碰系统必须先声明,用户侧可一键吊销。
二、沙箱的三种落地形态
-
Native 沙箱(默认)
- 插件进程用 Rust 的
tokio::process拉起,自带--sandbox参数时,自动加 seccomp-BPF 过滤器,屏蔽 300+ 系统调用(源码见crates/goose/src/sandbox/seccomp.rs)。 - 文件系统只挂载工作区子目录,父目录通过
open_tree+move_mount做只读绑定,防止../../../逃逸。 - 网络命名空间隔离,仅允许 Unix Domain Socket 与 Runtime 通信,TCP/UDP 默认全关。
- 插件进程用 Rust 的
-
Docker 沙箱(CI 推荐)
- 官方镜像
ghcr.io/block/goose-mcp:latest自带非 root 用户(uid=1000),入口脚本通过gosu降权。 - 默认
--cap-drop=ALL --cap-add=DAC_OVERRIDE,只保留修改文件权限的能力;--security-opt=no-new-privileges禁止提权。 - 通过
docker run --read-only --tmpfs /tmp:rw,noexec,nosuid,size=100m把可写目录限制在内存盘,重启即销毁。
- 官方镜像
-
Firecracker microVM(重度隔离)
- 对敏感仓库(含生产密钥)可在
.goose/config.yaml里开启vm = "firecracker",Goose 会调用/usr/bin/jailer启动 128 MB 微虚拟机,启动时间 180 ms,IO 性能下降 8%。 - 虚拟机内只挂
virtio-fs的 repo 目录,其余文件系统为空镜像,kernel 用官方精简 config,只保留 9 个系统调用。
- 对敏感仓库(含生产密钥)可在
三、用户可调的 7 个关键参数
把下面配置写进 $HOME/.goose/config.yaml,可在团队内部统一基线:
extensions: # 插件白名单,不在列表的即使安装也不加载
allowlist:
- id: filesystem
max_permission: read-write # 还可 read-only、deny
- id: docker
max_permission: deny # 完全禁用
sandbox:
level: docker # native | docker | firecracker
docker_image: ghcr.io/block/goose-mcp:1.16.1
cpu_limit: