入门 Zed Industries 2026-09-14 17:42:19 · 0 阅读

第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_hostsallow_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+/" }]
        }
      }
    }
  }
}

此示例自动批准终端工具中的 cargonpm 命令,同时要求对 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 正则表达式语法。默认情况下,匹配不区分大小写。

规则优先级

从最高到最低优先级如下:

  1. 内置安全规则:硬编码的保护措施(例如 rm -rf /)。无法被覆盖。
  2. always_deny:阻止匹配的操作
  3. always_confirm:需要确认匹配的操作
  4. always_allow:自动批准匹配的操作
  5. 特定工具的 default:当没有模式匹配时,作为每个工具的后备设置(例如 tools.terminal.default
  6. 全局 default:当未设置特定工具的后备设置时,回退到 tool_permissions.default

全局自动批准

要自动批准所有工具操作:

{
  "agent": {
    "tool_permissions": {
      "default": "allow"
    }
  }
}

这会绕过大多数工具的确认提示,但 always_denyalways_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_allowalways_deny 模式(当能提取出安全模式时)

选择"始终对 允许/拒绝"会将 tools.<tool>.default 设为允许或拒绝。 当能安全提取模式时,选择"始终对 允许/拒绝"会为该输入添加一条 always_allowalways_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 的沙箱机制主要应用于 terminalfetch 工具。

工具 沙箱限制内容
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 中 terminalfetch 工具的行为。它 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_hostsallow_fs_write_allallow_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 使用 Bubblewrapbwrap)实现沙箱。

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 的 ToolsPrompts 功能。我们欢迎有助于推进 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 服务器提供为扩展。您可以通过以下方式查找:

  1. Zed 网站
  2. 在应用中,打开 Command Palette 并运行 {#action zed::Extensions} 操作
  3. 在应用中打开 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 ServerAdd 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 的日志或文档。

评论 (0)