第23章 Zed AI Agent 工具指南:内置功能、权限配置与自定义 MCP 支持
Zed 内置的 Agent 可以调用这些工具来读取、搜索和编辑你的代码库。这些工具会在 Agent 面板中与你与 AI Agent 对话时被使用。
具体的工具列表可能因Agent 配置、所选模型提供商以及 Zed 版本而异。
你可以为工具操作配置权限,包括自动批准、自动拒绝,或在具体情况下需要你来确认。有关受权限限制的工具列表及详细信息,请参阅工具权限。
若要添加除这些内置工具以外的自定义工具,请参阅MCP 服务器。
若要选择在 Zed Agent 线程中可用的内置工具和 MCP 工具,请使用Agent 配置。配置控制工具的可用性;工具权限控制允许、拒绝和确认的行为。
启用Zed Agent 沙盒后,终端工具也可以运行在额外的操作系统级限制下。
读取与搜索工具
diagnostics
获取特定文件或整个项目的错误和警告。在代码编辑后使用此工具,判断是否还需要进一步修改。 提供路径时,显示该特定文件的所有诊断信息。 不提供路径时,显示项目中所有文件的错误和警告数量摘要。
示例:在编辑 src/parser.rs 后,使用该路径调用 diagnostics 以立即检查是否存在类型错误。在进行涉及大量文件的大型重构后,在不提供路径的情况下调用它,以查看项目范围内的错误总数,从而决定下一步要修复什么。
fetch
获取 URL 并以 Markdown 格式返回内容。适用于将文档作为上下文提供。
fetch 受工具权限、agent 配置文件和项目信任状态的管理。它不在终端 OS 沙箱内运行,因此终端沙箱的网络授权(如 allow_hosts 和 allow_all_hosts)对它不生效。
示例:在编写集成代码之前,先抓取某个库的 changelog 页面,确认最近的版本是否引入了破坏性的 API 变更。
find_path
通过 glob 模式匹配(如 "*/.js")快速查找文件,按字母顺序返回匹配到的文件路径。
grep
使用正则表达式在整个项目中搜索文件内容。在不知道具体文件路径的情况下查找代码中的符号时,优先使用这个工具。
示例:重命名函数前需要找到它的所有调用点,可以搜索 parse_config\( —— 这个正则会匹配函数名加左括号,从而过滤掉恰好包含该字符串的注释或变量名。
list_directory
列出指定路径下的文件和目录,提供文件系统内容的概览。
read_file
读取项目中指定文件的内容,用于访问文件内容。
Web 工具
search_web
在网络上搜索信息,返回相关网页的摘要和链接,适合获取实时信息。
示例:查询某个依赖的已知 bug 是否在最近版本中修复,或者本地文档过时的情况下查找第三方库当前版本的 API 签名。
注意:内置的
search_web工具仅对使用 Zed 提供方的 Zed Pro 订阅用户开放。如果你使用免费方案或其他提供方,可以连接提供网络搜索能力的 MCP 服务器来获得同等功能。详情参见 MCP servers。
编辑工具
copy_path
在项目中递归复制文件或目录。需要复制内容时,比手动读写文件更高效。
create_directory
在项目内指定路径创建新目录,并自动创建所有必需的父级目录(类似于 mkdir -p)。
delete_path
删除指定路径下的文件或目录(包括递归删除其内容),并确认删除操作。
edit_file
通过替换特定文本为新内容来编辑文件。
示例: 更新函数签名——agent 会识别需要替换的精确行并提供更新版本,而保持周围代码不变。对于大规模重命名,它会配合使用 grep 先找出所有出现位置。
move_path
在项目内移动或重命名文件或目录;若仅文件名不同,则执行重命名操作。
write_file
创建新文件,或用完全新的内容覆盖现有文件。
terminal
执行 shell 命令并返回合并后的输出,每次调用都会创建一个新的 shell 进程。
示例: 编辑完 Rust 文件后,运行 cargo test --package my_crate 2>&1 | tail -30 确认变更不会破坏现有测试。或者运行 git diff --stat,在结束任务前检查哪些文件已被修改。
其他工具
skill
从可用的 Skill 加载指令,使 agent 能够遵循项目特定或工作流特定的指导。你也可以通过斜杠命令直接调用这些 Skill。
示例: 当仓库中有一个用于编写发布说明的 skill 时,agent 可以在起草发布说明前加载该 skill,以确保遵循本地格式。
spawn_agent
生成一个拥有独立上下文的子 agent 来执行委托任务。适用于并行调查、完成自包含任务,或进行仅关注最终结果的研究。每个子 agent 都可以访问与父 agent 相同的工具。
示例: 在重构认证模块时,生成一个子 agent 去调查代码库其他位置中会话令牌的验证方式。父 agent 继续其工作,并在子 agent 完成后审查其发现——这样两个上下文窗口都能专注于单一任务。
工具权限
配置哪些 Agent Panel 工具可自动运行,哪些需要手动批准。 查看 Tools 页面 可获取可用工具列表。
注意: 在 Zed v0.224.0 及更高版本中,工具审批由
agent.tool_permissions.default控制。 在早期版本中,该功能由agent.always_allow_tool_actions布尔值控制(默认值为false)。
快速入门
使用 Zed 的设置编辑器配置工具权限,或者直接在你的设置文件中添加规则:
{
"agent": {
"tool_permissions": {
"default": "allow",
"tools": {
"terminal": {
"default": "confirm",
"always_allow": [
{ "pattern": "^cargo\\s+(build|test|check)" },
{ "pattern": "^npm\\s+(install|test|run)" }
],
"always_confirm": [{ "pattern": "sudo\\s+/" }]
}
}
}
}
}
此示例自动批准终端工具中的 cargo 和 npm 命令,同时要求对 sudo 命令进行手动逐项确认。
非终端命令遵循全局 "default": "allow" 设置,但工具特定的默认设置和 always_confirm 规则仍可能触发提示。
工作原理
tool_permissions 设置允许你通过指定正则表达式模式来自定义工具权限,这些模式用于:
- 自动批准你信任的操作
- 自动拒绝危险操作(即使
tool_permissions.default设为"allow"也会被阻止) - 始终确认敏感操作,无论其他设置如何
支持的工具
| 工具 | 匹配输入内容 |
|---|---|
terminal |
Shell 命令字符串 |
edit_file |
文件路径 |
write_file |
文件路径 |
delete_path |
要删除的路径 |
move_path |
源路径和目标路径 |
copy_path |
源路径和目标路径 |
create_directory |
目录路径 |
fetch |
URL |
search_web |
搜索关键词 |
skill |
技能 SKILL.md 文件的绝对路径 |
MCP 工具的格式为 mcp:<server>:<tool_name>。例如,github 服务器上名为 create_issue 的工具应写作 mcp:github:create_issue。
对于由模型调用的 Skills,使用 skill 工具。用户通过 /skill-name 斜杠命令调用的技能不会再弹出提示,因为你已明确触发了该技能。
配置
{
"agent": {
"tool_permissions": {
"default": "confirm",
"tools": {
"<tool_name>": {
"default": "confirm",
"always_allow": [{ "pattern": "...", "case_sensitive": false }],
"always_deny": [{ "pattern": "...", "case_sensitive": false }],
"always_confirm": [{ "pattern": "...", "case_sensitive": false }]
}
}
}
}
}
选项
| 选项 | 说明 |
|---|---|
default |
没有匹配到任何模式时的兜底行为:"confirm"(默认)、"allow" 或 "deny" |
always_allow |
匹配即自动放行的模式(除非同时匹配到 deny 或 confirm) |
always_deny |
匹配即直接拦截的模式——优先级最高,不可被覆盖 |
always_confirm |
这些模式始终会触发确认提示,即使 tool_permissions.default 设置为 "allow" |
模式语法
{
"agent": {
"tool_permissions": {
"tools": {
"edit_file": {
"always_allow": [
{
"pattern": "your-regex-here",
"case_sensitive": false
}
]
}
}
}
}
}
模式使用 Rust 正则表达式语法。默认情况下,匹配不区分大小写。
规则优先级
从最高到最低优先级如下:
- 内置安全规则:硬编码的保护措施(例如
rm -rf /)。无法被覆盖。 always_deny:阻止匹配的操作always_confirm:需要确认匹配的操作always_allow:自动批准匹配的操作- 特定工具的
default:当没有模式匹配时,作为每个工具的后备设置(例如tools.terminal.default) - 全局
default:当未设置特定工具的后备设置时,回退到tool_permissions.default
全局自动批准
要自动批准所有工具操作:
{
"agent": {
"tool_permissions": {
"default": "allow"
}
}
}
这会绕过大多数工具的确认提示,但 always_deny、always_confirm、内置安全规则以及 Zed 设置目录内的路径仍会触发提示或阻止操作。
Shell 兼容性
对于 terminal 工具,Zed 会解析链式命令(例如 echo hello && rm file),将每个子命令与你的模式进行检查。
所有支持的 shell 都能与工具权限模式配合使用,包括 sh、bash、zsh、dash、fish、PowerShell 7+、pwsh、cmd、xonsh、csh、tcsh、Nushell、Elvish 和 rc (Plan 9)。
编写模式
- 使用
\b表示单词边界:\brm\b会匹配 "rm",但不会匹配 "storm" - 使用
^和$将模式锚定在输入的开头/结尾 - 转义特殊字符:用
\.匹配字面量点号,用\\匹配反斜杠
务必仔细测试——拒绝模式中的拼写错误会误阻正常操作。 你可以使用每个工具页面提供的"测试规则"检查器,确认模式是否落入预期条件。
内置安全规则
Zed 内置了一组硬编码的安全规则,任何设置都无法覆盖。 这些规则仅适用于 终端 工具,用于阻止递归删除关键目录:
rm -rf /和rm -rf /*— 文件系统根目录rm -rf ~和rm -rf ~/*— 用户主目录rm -rf $HOME/rm -rf ${HOME}(以及$HOME/*) — 通过环境变量访问的主目录rm -rf .和rm -rf ./*— 当前目录rm -rf ..和rm -rf ../*— 父目录
这些模式可捕获任意标志组合(如 -fr、-rfv、-r -f、--recursive --force),且不区分大小写。
它们会同时检查原始命令和链式命令中解析出的每个子命令(例如 ls && rm -rf /)。
除此之外没有其他内置规则。
默认设置文件({#action zed::OpenDefaultSettings})中包含了注释掉的示例,用于保护 .env 文件、机密目录和私钥——你可以根据需要取消注释或修改这些内容。
UI 中的权限请求
当代理请求权限时,你会在对话视图中看到一个工具卡片,其菜单包含:
- 允许一次 / 拒绝一次 — 一次性决定
- 始终对
允许/拒绝 — 设置工具级别的默认允许或拒绝 - 始终对
允许/拒绝 — 添加一个always_allow或always_deny模式(当能提取出安全模式时)
选择"始终对 tools.<tool>.default 设为允许或拒绝。
当能安全提取模式时,选择"始终对 always_allow 或 always_deny 规则。
MCP 工具仅支持工具级别的选项。
示例
终端:自动放行构建命令
{
"agent": {
"tool_permissions": {
"tools": {
"terminal": {
"default": "confirm",
"always_allow": [
{ "pattern": "^cargo\\s+(build|test|check|clippy|fmt)" },
{ "pattern": "^npm\\s+(install|test|run|build)" },
{ "pattern": "^git\\s+(status|log|diff|branch)" },
{ "pattern": "^ls\\b" },
{ "pattern": "^cat\\s" }
],
"always_deny": [
{ "pattern": "rm\\s+-rf\\s+(/|~)" },
{ "pattern": "sudo\\s+rm" }
],
"always_confirm": [
{ "pattern": "sudo\\s" },
{ "pattern": "git\\s+push" }
]
}
}
}
}
}
文件编辑:保护敏感文件
{
"agent": {
"tool_permissions": {
"tools": {
"edit_file": {
"default": "confirm",
"always_allow": [
{ "pattern": "\\.(md|txt|json)$" },
{ "pattern": "^src/" }
],
"always_deny": [
{ "pattern": "\\.env" },
{ "pattern": "secrets?/" },
{ "pattern": "\\.(pem|key)$" }
]
}
}
}
}
}
路径删除:阻止删除关键目录
{
"agent": {
"tool_permissions": {
"tools": {
"delete_path": {
"default": "confirm",
"always_deny": [
{ "pattern": "^/etc" },
{ "pattern": "^/usr" },
{ "pattern": "\\.git/?$" },
{ "pattern": "node_modules/?$" }
]
}
}
}
}
}
URL 抓取:控制外部访问
{
"agent": {
"tool_permissions": {
"tools": {
"fetch": {
"default": "confirm",
"always_allow": [
{ "pattern": "docs\\.rs" },
{ "pattern": "github\\.com" }
],
"always_deny": [{ "pattern": "internal\\.company\\.com" }]
}
}
}
}
}
MCP 工具
{
"agent": {
"tool_permissions": {
"tools": {
"mcp:github:create_issue": {
"default": "confirm"
},
"mcp:github:create_pull_request": {
"default": "confirm"
}
}
}
}
}
Skills
skill 工具的模式匹配对象是 Skill 的 SKILL.md 文件的绝对路径,而非 Skill 名称。
{
"agent": {
"tool_permissions": {
"tools": {
"skill": {
"default": "confirm",
"always_allow": [{ "pattern": "/code-review/SKILL\\.md$" }]
}
}
}
}
}
若要禁止模型调用某个 Skill,请将该 Skill 的 SKILL.md 文件中的 disable-model-invocation 设置为 true。详见 Skills。
沙箱隔离
你可以通过多种方式限制 Zed Agent 执行的操作。其中一种限制方式是使用 工具权限,但当 Agent 试图在终端执行复杂脚本时,这种方式的作用有限。
沙箱机制利用操作系统特性,强制限制工具调用可访问的资源范围。它不依赖于 Agent 遵守特定指令。若 Agent 试图访问被沙箱限制的资源,操作系统将直接拦截该请求。关于沙箱的可信度详情,请参阅我对沙箱的信任程度如何?。
工具权限可以与沙箱机制配合使用:
- 工具权限旨在从源头上限制 Agent 执行特定工具操作的能力
- 当工具操作实际运行时,沙箱机制会限制其行为
沙箱机制仅适用于 Zed Agent。Zed 本身、语言服务器、扩展、任务、普通终端标签页、外部 Agent 或 终端线程均不在沙箱保护范围内。
注意:在特定条件下,Windows 上的沙箱安全性弱于 Linux 和 macOS,可能无法阻止所有逃逸尝试。详情请参阅Windows章节。
沙箱化工具
目前,Zed Agent 的沙箱机制主要应用于 terminal 和 fetch 工具。
| 工具 | 沙箱限制内容 |
|---|---|
terminal |
Agent 执行的命令涉及的写文件系统操作及出站网络访问;Git 元数据受保护。 |
fetch |
可访问的主机范围。 |
这些工具仍受 工具权限、Agent 配置文件及项目信任机制的管控,但目前尚未纳入此操作系统级沙箱中。
环境要求
所有平台均支持某种形式的沙箱机制。若要为 terminal 工具调用启用沙箱,需满足以下条件:
- 在 Linux 系统上,
$PATH中必须存在可运行且非 setuid 的bwrap二进制文件。参见安装 Bubblewrap。 - 在 Windows 系统上,必须可用 WSL。
macOS 无需额外要求。
fetch 工具在所有平台上均无额外要求。
默认访问权限
默认情况下,处于沙箱中的 Zed Agent 工具操作具有以下限制:
| 访问类型 | 默认行为 |
|---|---|
| 文件系统读取 | 终端命令可以读取文件系统的大部分内容,包括受保护的 Git 元数据。 |
| 项目写入 | 终端命令可以在已打开的项目目录内写入,但受保护的 Git 元数据除外。 |
| Git 元数据 | .git 目录及关联 worktree 的 Git 元数据保持可读,但在沙箱中不可写。 |
| 临时文件 | 终端命令会获得一个可写的临时目录,具体行为因平台而异。 |
| 其他写入 | 默认可写位置之外的写入操作会被阻止,除非你批准更大范围的沙箱请求。 |
| 对外网络 | 网络访问默认被阻止,除非你批准针对特定主机的或无限制的网络沙箱请求。注意,针对特定主机的限制并非在所有平台上都可用。 |
| 本地 IPC 套接字 | 沙箱中的命令无法打开 Unix 域套接字(例如连接桌面会话总线或容器守护进程),否则这些套接字可能被用来在沙箱外执行命令。 |
沙箱到底有多可信?
启用沙箱能大幅降低各类攻击的风险,但并不能完全消除。
首先,沙箱依赖操作系统层面的特性,而这些特性本身可能有 bug。操作系统的安全功能历来出现过漏洞;即便我们做了充分测试,Zed 的实现也可能存在 bug。这些问题可能导致权限提升——比如让 Agent 写入它本应只有读取权限的文件。
其次,沙箱只强制执行用户授权的限制。如果 Agent 请求了对你主目录的写权限,沙箱不会(也不应该)阻止它往 $HOME/.ssh 里添加恶意密钥。
所以请谨慎授予 Agent 权限。你可以随时把鼠标悬停在线程右上角的挂锁图标上,查看当前沙箱状态。如果 Agent 请求了过于宽泛的权限,直接拒绝,并让它改用更小的授权范围。Agent 在请求提权时必须提供 reason,会显示在提示中——请先读一读,确认合理后再批准。
另外,沙箱仅限制 Zed agent 中 terminal 和 fetch 工具的行为。它对 Zed 的其他部分没有影响,包括:
- 语言服务器
- 内置的 Git 客户端
- 常规终端
- 等等...
即使启用了沙箱,你也应保持警惕。恶意或未对齐的 agent 可能会利用这些侧信道提升权限。例如:
- Agent 可能会向你的代码库中添加恶意的 Rust 过程宏,这将在沙箱外部被
rust-analyzer自动执行。 - Agent 可能会修改
Makefile以注入恶意脚本,当你在内置终端中运行make时,该脚本将在沙箱外部执行。 - 虽然 agent 无法写入你仓库受保护的
.git目录,但它可以在你的项目下创建一个子模块,并完全控制该子模块的 Git 元数据(包括core.fsmonitor等配置)。随后,当你在常规终端中运行 Git 命令时,这些元数据可能会在沙箱外部被执行。甚至你的 Shell 提示符也可能在每次渲染时执行 Git 命令!
你可以采取措施来缓解这些问题。例如:
- 禁用那些会从项目中执行用户定义代码(如 Rust 过程宏)的语言服务器。
- 使用一种不执行仓库定义程序来报告 Git 状态的 Shell 提示符。
- 在运行
git commit之前审查 diff。
但这些都无法改变一个基本原则:沙箱不能替代良好的安全实践。它只是纵深防御策略中的一层。
Zed 的默认配置文件旨在平衡安全性和便利性,但我们鼓励你根据自己的安全需求和风险状况调整设置。未启用的沙箱不是一个有效的沙箱。
审批提示
当 agent 需要访问默认沙箱之外的资源时,Zed 会在工具操作运行前显示沙箱审批提示。 根据工具的具体请求,提示可能会要求你允许:
- 访问特定主机(如
github.com或*.npmjs.org)的网络连接 - 访问任何主机的网络连接
- 访问特定文件系统路径的写入权限
- 不受限的文件系统写入,但受保护的 Git 元数据除外
- 在沙箱外运行终端命令
你可以为沙箱请求授予以下权限:
- 单个工具动作
- 当前线程的剩余部分
- 始终允许
针对线程剩余部分的批准仅在该线程内有效。选择“始终允许”的批准会保存在
settings.json 文件的 agent.sandbox_permissions 字段下。
持久化沙箱权限
如果你希望预先批准常见的沙箱请求,请在你的设置文件中添加持久化权限:
{
"agent": {
"sandbox_permissions": {
"network_hosts": ["github.com", "*.npmjs.org"],
"write_paths": ["/Users/you/.cache/my-tool"]
}
}
}
可用的选项如下:
| 设置项 | 描述 |
|---|---|
network_hosts |
沙箱工具可访问而无需提示的主机列表。条目可以是精确的主机名,也可以是带 * 前缀的通配符(如 *.)。 |
allow_all_hosts |
允许沙箱工具访问任何主机而无需提示。 |
write_paths |
沙箱终端命令可写入的目录子树,无需提示。路径必须是绝对路径。 |
allow_fs_write_all |
允许沙箱终端命令写入除受保护 Git 元数据外的任何位置,无需提示。 |
allow_unsandboxed |
完全关闭 Zed Agent 终端命令的沙箱机制。此时 fetch 工具将不受限制。 |
建议优先授予窄范围的权限,例如特定主机或写入路径,而非使用 allow_all_hosts、allow_fs_write_all 或
allow_unsandboxed。
Git 元数据
当终端命令在沙箱中运行时,无法授予 Git 元数据的写入权限。这包括对 .git 目录、关联的 worktree 元数据、refs、索引、hooks、本地 Git 配置以及其他由 Git 控制的元数据文件的写入。即使批准了特定的可写路径或 allow_fs_write_all,Git 元数据仍然不可写。
平台支持
沙箱机制在每个操作系统平台上使用不同的底层实现。用户看到的提示类似,但具体的执行细节有所差异。
macOS
在 macOS 上,Zed 通过 sandbox-exec 使用 Apple 的 Seatbelt 沙箱。
沙箱化的终端命令:
- 可以读取文件系统
- 可以在已打开的项目目录内写入,受保护的 Git 元数据除外
- 可以写入通过
$TMPDIR、$TMP、$TEMP暴露的每线程临时目录 - 可以读取受保护的 Git 元数据
- 不能写入受保护的 Git 元数据,即使你批准了更宽泛的写权限也不行
- 不能写入其他位置,除非你批准了额外路径或更宽泛的写权限
- 不能访问网络,除非你批准了网络访问
- 只能访问开发者工具所需的 macOS 系统(Mach)服务白名单;可能被用来逃逸沙箱的服务(LaunchServices 和 launchd,它们可以在沙箱外启动进程)、读取剪贴板的服务(pasteboard)以及捕获音频的服务均不可访问
在 macOS 上批准网络访问后,Zed 会使用 HTTP/HTTPS 代理,从而将访问限制在已批准的主机内。 不遵循代理环境变量的工具(如 SSH、FTP 和原始 socket 客户端)即使批准了特定主机的网络访问,也可能无法正常工作。 对于需要联网的终端命令,尽量优先使用 HTTPS URL 而非 SSH URL。
Linux
在 Linux 上,Zed 使用 Bubblewrap(bwrap)实现沙箱。
Zed 只使用非 setuid 的 bwrap 二进制文件。其沙箱完全基于非特权 user namespace 构建,因此 setuid-root 的 bwrap 并不提供额外功能,运行它反而意味着以 root 权限执行参数部分来自模型影响输入的设置操作。如果 PATH 中找到的 bwrap 只有 setuid-root 版本,Zed 会拒绝运行;请安装非 setuid 的 Bubblewrap 以启用沙箱。
沙箱化的终端命令:
- 可以读取文件系统,包括受保护的 Git 元数据内容
- 可以在已打开的项目目录内写入,受保护的 Git 元数据除外
- 可写入
/tmp目录,该目录由全新的临时文件系统提供支持,并在每次终端工具调用之间被清空(如果你批准了不受限的文件系统写入权限,/tmp将指向宿主机上真实的/tmp目录,而非全新的临时文件系统) - 无法写入受保护的 Git 元数据
- 除非你批准了额外的路径或更广泛的写入权限,否则无法写入其他位置
- 除非你批准了网络访问权限,否则无法访问网络
在 Linux 上,如果批准了针对特定主机的网络访问,Zed 会使用 HTTP/HTTPS 代理,以便将访问限制在已批准的主机范围内。对于不遵循代理环境变量的工具(如 SSH、FTP 和原始套接字客户端),即使获批特定主机的网络访问,也可能无法正常工作。
如果 Bubblewrap 不可用或无法在当前环境中创建沙箱,Zed 可能会在无操作系统沙箱限制的情况下运行命令,并在工具输出中显示警告。
警告:在 Linux 和 WSL 上,对文件系统对象的限制是在沙箱创建时确定的。这意味着,除了其他情况外,如果代理被授予对非 Git 仓库目录
/foo的访问权限,它可能会创建/foo/.git。有关此限制的更详细影响,请参阅 我能多大程度信任沙箱?。
安装 Bubblewrap
Zed 需要你的 $PATH 中有一个可运行的、非 setuid 的 bwrap 二进制文件。通常,只需通过发行版的包管理器安装 bubblewrap 即可。
你可以通过以下命令测试其是否正常工作:
bwrap --ro-bind / / -- echo "working"
此处的“非 setuid”指的是setuid 位。历史上,bubblewrap 同时发布过 setuid 和非 setuid 二进制文件。出于安全考虑,setuid 二进制文件正在逐步被淘汰,因此 Zed 的沙箱明确拒绝使用 setuid 版本的 bwrap 二进制文件。
Ubuntu 特定要求
注意:以下内容不适用于 WSL 上的 Ubuntu。
Bubblewrap 依赖 Linux 内核中一项名为“命名空间”(namespaces)的特性。在许多系统上,非特权用户也可以创建命名空间,但历史上,该特性曾被用于多种攻击手段。
作为应对措施,Canonical 在 Ubuntu 23.10 中 增加了一项安全措施,用于限制非特权用户命名空间。这些限制由 AppArmor 强制执行。
因此,安装 bubblewrap 后,您可能还需要为其安装一个 AppArmor 配置文件。该配置文件赋予 bubblewrap 创建命名空间的权限,无需使用 sudo 提权。
sudo apt install bubblewrap
# On Ubuntu 25.04 and later, `apparmor` ships with a profile for bubblewrap by default.
# Make sure you're up-to-date
sudo apt install --only-upgrade apparmor
# On older versions, manually install the profile
sudo apt update
sudo apt install apparmor-profiles apparmor-utils
sudo install -m 0644 \
/usr/share/apparmor/extra-profiles/bwrap-userns-restrict \
/etc/apparmor.d/bwrap-userns-restrict
sudo apparmor_parser -r /etc/apparmor.d/bwrap-userns-restrict
Windows
在 Windows 上,Zed Agent 沙箱功能仅在代理操作运行于 WSL 内部时受到支持。
警告:受限于 WSL 的实现机制,如果用户对位于 NTFS 驱动器上的任意路径拥有写权限,终端命令可能会在沙箱授权范围之外进行写入操作。这包括存储在 NTFS 上的当前项目授权。发生此类情况时,Zed 会显示警告。实际上,我们认为利用此缺陷进行攻击难度较大,但无法保证绝对安全。更多技术细节请参阅下文。
在 WSL 内部,Zed 使用 Linux 的 Bubblewrap 沙箱,因为 WSL 提供了 Bubblewrap 所需的 Linux 进程和文件系统原语。目前,原生 Windows 进程在 Zed 中尚不支持相同的沙箱集成,因此原生 Windows 命令无法像代理操作那样被 Zed Agent 的操作系统沙箱严格限制。
在 WSL 中运行时,将应用 Linux 的沙箱机制,包括要求 bwrap 不能被设置为 setuid-root:
- 文件系统隔离由 Bubblewrap 提供
- 受保护的 Git 元数据内容保持可读,但禁止写入
- 沙箱化终端调用中的
/tmp目录是临时的 - 网络访问是全有或全无的,无法按主机区分,所以针对特定主机的网络请求会被拒绝,需要联网时代理必须申请完全开放的网络访问权限
如果未安装 WSL,或者你选择不在沙箱中运行命令,Zed 会退回到标准终端行为,在本地 shell 中运行。它会按常规的优先级顺序选择 shell:安装了 bash(scoop 的 bash 或 Git Bash)就用 bash,否则用 PowerShell,最后是 cmd.exe。此时命令运行在原生 Windows 路径下而非 WSL 的 Linux 文件系统,路径约定也会随之变化(例如 C:\... 或 /c/...,而不是 WSL 的 /mnt/c/...),因此为沙箱化 WSL shell 编写的命令可能会表现不同。
为什么 NTFS 对象会破坏沙箱?
总的来说,文件系统沙箱的安全性依赖两项内容的匹配:
- 用户批准时看到的路径
- 实际被授权访问的文件系统对象
如果用户以为自己授权的是 /foo/hello,实际上授权的却是 /bar/world,那沙箱就失效了。
在 Linux 上,这个"文件系统对象"叫做 inode。
但 /foo/hello 并不指向某个 inode。粗略地说,它指向的是一个 inode 可能存在的位置。它在某一时刻可能对应一个 inode,之后又对应另一个。
而且由于符号链接的存在,一个拥有 /foo 写权限的代理,即使没有 /secret 的写权限,也可能把 /foo/bar 改为指向 /secret。一旦发生这种情况,即使代理有 /foo 的访问权限,我们也不能再授予它 /foo/bar 的访问权限,因为那等于间接授权访问 /secret。
这意味着我们只能引用满足以下条件的路径:
- 规范化(即不含符号链接)
- 绝对路径
- 自验证后未发生变化
在非 WSL 的 Linux 上,我们可以直接打开路径获取"文件描述符",它能直接标识 inode,持有该文件描述符就相当于"锁定"了正确的 inode。当路径指向 Linux 文件系统中的对象时,这个方法在 WSL 上同样有效。
不过,WSL 允许访问存储于 Windows 磁盘中的文件。例如,Windows 路径 C:\foo\bar.txt 对应于 Linux 下的 /mnt/c/foo/bar.txt,其机制类似于网络驱动器。遗憾的是,针对这类文件的 inode 锁定无法保证生效。虽然我们可以锁定 /mnt/c/foo/bar.txt 的 inode,但这并不等同于锁定了底层的 Windows 文件系统对象。因此,在沙箱生命周期内,该对象仍可能发生变动,从而可能允许写入操作突破沙箱边界。
实际中这一风险有多大?
在测试中,我们无法利用此漏洞逃逸出沙箱。
在实际使用中,这种映射关系往往相当稳定。原因在于,Linux 文件系统中生成的 inode 源自文件引用(非常粗略地讲,类似“Windows inode”),其稳定性与 Linux inode 相近。标准的“重命名子组件”攻击似乎会产生不同的 inode 编号,导致沙箱内的检查采取 fail-closed 策略。
但关键在于,这并非绝对保证。这只是我们在测试中观察到的行为,却找不到任何文档能保证此行为在所有情况下、对所有新旧版本的 Windows/WSL 以及任意配置选项均有效。
Zed 的沙箱设计目标是为做到完全不可攻破,即使面对一个具备完全控制力、能完全操纵项目文件并运行于标准用户环境下的有动机攻击者。它不假设代理是“总体善意但偶尔粗心”的。
鉴于此,我们无法像对待更常规场景那样,对沙箱安全性做出同等保证。然而,即使保证程度有所削弱,沙箱仍能让你比不启用时安全得多,因此值得保持启用。
选择批准内容
审查沙箱提示时,优先选择能让任务继续进行的最小权限:
- 当目标主机已知时,仅批准特定主机而非所有主机
- 仅批准特定写入路径,而非无限制的文件系统写入
- 仅当命令在沙箱内无法运行时,才批准无沙箱执行
- 对不熟悉的命令使用一次性批准
- 仅对预期会复用的访问使用线程级或永久批准
如果命令因沙箱阻止访问而失败,在批准更广泛的请求之前,请先询问 Agent 为什么需要该权限。
Zed 中的 Model Context Protocol (MCP)
Zed 使用 Model Context Protocol 与上下文服务器进行交互。
Model Context Protocol (MCP) 是一种开放协议,用于通过标准接口将 LLM 应用连接到外部工具和数据源。
支持的功能
Zed 目前支持 MCP 的 Tools 和 Prompts 功能。我们欢迎有助于推进 Zed MCP 功能覆盖范围(如 Discovery、Sampling、Elicitation 等)的贡献。
Zed 还处理来自 MCP 服务器的 notifications/tools/list_changed 通知。当服务器在运行时添加、移除或修改其可用工具时,Zed 会自动重新加载工具列表,无需重启服务器。
Agent 路径支持
| Agent 路径 | MCP 行为 |
|---|---|
| Zed Agent | 直接使用 Zed 配置的 MCP 服务器 |
| External Agents | Zed 可通过 ACP 转发已配置的 MCP 服务器;Agent 也可以读取原生 MCP 配置 |
| Terminal Threads | 原生 CLI/TUI 读取其自身的 MCP 配置 |
安装 MCP 服务器
作为扩展
在 Zed 中使用 MCP 服务器的方式之一是将其暴露为扩展。查看 MCP Server Extensions 页面以了解如何创建自己的扩展。
许多 MCP 服务器提供为扩展。您可以通过以下方式查找:
- Zed 网站
- 在应用中,打开 Command Palette 并运行 {#action zed::Extensions} 操作
- 在应用中打开 Settings → AI → MCP Servers,点击
Add Server,然后选择Install from Extensions
以下是一些以扩展形式提供的常用 MCP 服务器:
以自定义服务器方式添加
创建扩展并不是在 Zed 中使用 MCP 服务器的唯一方式。你可以在 Settings → AI → MCP Servers 中连接本地和远程 MCP 服务器(也可以通过 {#action agent::OpenSettings} 操作打开设置,然后选择 MCP Servers)。点击页面顶部的 Add Server,再选择 Add Local Server 或 Add Remote Server。你指定的配置会在设置文件中(可通过 {#action zed::OpenSettingsFile} 打开)生成类似下面这样的条目:
{
"context_servers": {
"local-mcp-server": {
"command": "some-command",
"args": ["arg-1", "arg-2"],
"env": {}
},
"remote-mcp-server": {
"url": "https://example.com/mcp",
"headers": { "Authorization": "Bearer <token>" }
},
"remote-mcp-server-with-oauth": {
"url": "https://mcp.example.com/mcp"
}
}
}
注意:如果远程 MCP 服务器没有配置
"Authorization"请求头,Zed 会提示你通过标准的 MCP OAuth 流程对服务器进行身份验证。
使用 MCP 服务器
配置检查
大多数 MCP 服务器在安装后还需要进行配置。
安装扩展后,Zed 会弹出窗口,提示你需要完成哪些设置才能正确使用该扩展。例如,GitHub MCP 扩展要求你添加一个个人访问令牌。
对于自定义服务器,请务必查阅提供商的文档,确定 JSON 中需要添加的命令、参数和环境变量类型。
要检查 MCP 服务器是否配置正确,请打开设置 → AI → MCP 服务器,并留意名称旁边的指示点。如果运行正常,指示点会显示绿色,且提示信息为“Server is active”。若不正常,其他颜色及提示信息会指示当前状态。
使用 Agent 面板
安装完成后,你可以返回 Agent 面板开始输入提示词。
MCP 工具调用的可靠性因模型而异。在提示中提及 MCP 服务器名称,有助于模型选择该服务器提供的工具。
然而,若希望确保使用某个 MCP 服务器,你可以创建自定义配置,关闭所有内置工具(或可能与服务器工具产生冲突的工具),仅开启该 MCP 服务器提供的工具。
例如,Dagger 团队建议对其Container Use MCP 服务器采用此方式:
"agent": {
"profiles": {
"container-use": {
"name": "Container Use",
"tools": {
"fetch": true,
"copy_path": false,
"find_path": false,
"delete_path": false,
"create_directory": false,
"list_directory": false,
"diagnostics": false,
"read_file": false,
"move_path": false,
"grep": false,
"edit_file": false,
"terminal": false
},
"enable_all_context_servers": false,
"context_servers": {
"container-use": {
"tools": {
"environment_create": true,
"environment_add_service": true,
"environment_update": true,
"environment_run_cmd": true,
"environment_open": true,
"environment_file_write": true,
"environment_file_read": true,
"environment_file_list": true,
"environment_file_delete": true,
"environment_checkpoint": true
}
}
}
}
}
}
工具权限
注意:在 Zed v0.224.0 及以上版本中,工具审批由
agent.tool_permissions.default控制。 在早期版本中,该行为由布尔值agent.always_allow_tool_actions(默认false)控制。
Zed 的 Agent 面板提供 agent.tool_permissions.default 设置,用于控制原生 Zed agent 的工具审批行为:
"confirm"(默认)— 在执行任何工具操作(包括 MCP 工具调用)前提示批准"allow"— 自动批准工具操作,无需提示"deny"— 阻止所有工具操作
如果想对具体的 MCP 工具进行细粒度控制,可以为每个工具配置权限规则。MCP 工具使用 mcp:<server>:<tool_name> 这样的键格式,例如 mcp:github:create_issue。对 MCP 工具来说,每个工具条目中的 default 键是主要的配置方式,因为基于模式的规则在匹配 MCP 工具时会匹配空字符串,大多数模式都无法命中。
了解更多关于工具权限的工作原理、进一步的定制方法及其他细节。
External Agents
在 Zed 中配置的 MCP 服务器会通过 Agent Client Protocol 转发给 External Agents。External Agents 也可以通过自身的原生配置文件访问 MCP 服务器。
关于 Zed 与 External Agents 之间共享哪些配置,详见配置边界。
错误处理
当 MCP 服务器在处理工具调用时出错,agent 会直接收到错误信息,操作失败。常见错误场景包括:
- 传给工具的参数无效
- 服务器端故障(数据库连接问题、速率限制)
- 操作不受支持或资源缺失
context server 的错误信息会显示在 agent 的回复中,方便你诊断并修复问题。具体错误代码的含义,请查阅 context server 的日志或文档。