VS Code 最近把 Agent 的执行安全问题摆到了更显眼的位置:Copilot Agent 不再只是生成文本,它还可能执行终端命令、启动语言服务器、调用 MCP Server,并访问网络。于是,很多人第一次遇到 Permission denied、命令无法启动、依赖下载失败,或者看到“Allow Outside Sandbox”时,往往不知道这是权限问题、沙箱策略问题,还是运行环境缺少依赖。

本文以 VS Code 的 Copilot harness sessions(使用共享运行时默认工具的 Agent 会话)为范围,目标不是只解释概念,而是让你能完成三件事:

  1. 知道沙箱保护什么、不保护什么;
  2. 遇到拦截时,能按证据定位并用最小权限修复;
  3. 能在 settings.json 中配置文件系统、网络、MCP、语言服务器和凭据访问。

文中设置名称和默认值以 VS Code 官方文档当前版本为准。不同版本、远程主机和组织策略可能导致可见选项不同。

1. VS Code Agent 沙箱是什么

1.1 它限制的是 Agent 进程的活动范围

Agent 沙箱会约束终端命令及其子进程可以访问的:

  • 文件系统:哪些目录可读写、只读或完全拒绝;
  • 网络:是否允许出站访问、是否允许访问本地网络、哪些域名可访问;
  • 附属进程:由 Agent Host 启动或管理的 MCP Server、语言服务器;
  • 凭据代理:是否向沙箱内的 Git 和 GitHub CLI 操作提供认证能力。

沙箱是“进程级限制”,不是虚拟机,也不是新的操作系统用户。沙箱中的程序仍然以你的账户运行在当前执行主机上,因此它不能替代终端安全软件、容器或云端隔离。尤其要注意:允许网络、额外目录、凭据或“沙箱外执行”,都会扩大信任边界。

1.2 沙箱和审批是两层机制

这两个概念很容易混在一起:

机制 解决的问题
审批(Approvals) 这一次操作是否需要你确认,或者是否可以自动执行
沙箱(Sandboxing) 即使操作执行,它能看到哪些文件和网络资源

例如,选择 Allow all 只改变审批层,并不意味着沙箱会自动放开文件系统和网络限制。反过来,给命令加了沙箱外执行的批准,也不等于给所有后续命令永久开放权限;是否允许会受到会话选择和组织策略影响。

1.3 默认不一定启用,而且“启用”不等于断网

官方设置 chat.agent.sandbox.enabled 的默认值是 off。启用后,沙箱默认仍允许出站网络(chat.agent.sandbox.network.allowNetwork 默认是 true),所以它不是“联网开关”,而是“限制联网范围的基础设施”。需要断网或限制域名时,还要显式配置网络设置。

2. 平台和执行位置:先确认你改的是哪台机器

沙箱在哪里生效,取决于 Agent 实际运行命令的主机:

  • 本地窗口:通常是本机;
  • SSH、WSL、Dev Container 或 Codespace:通常是远端主机、Linux 子系统或容器;
  • 远程会话:路径和设置都以执行主机为准,不是你操作 VS Code 的那台电脑。

因此,“我已经在 macOS 上安装了依赖”并不能证明 WSL 或远程容器里也满足条件。

官方平台要求大致如下:

  • macOS:macOS 15 或更高版本,使用系统内置 Seatbelt,不需要额外安装沙箱包;
  • glibc Linux / WSL2:需要 bubblewrap 0.5.0+、slirp4netns、util-linux 2.35+ 和兼容的 iptables 工具;
  • Windows:Windows 11 的 BaseContainer 能力和对应更新基线,当前支持为 Experimental;
  • Alpine 等 musl Linux:当前运行时不支持沙箱 Shell;
  • WSL1:不支持,因为缺少 bubblewrap 所需的 Linux 内核能力。

3. 开启沙箱并确认是否真的生效

3.1 在 settings.json 中开启

打开命令面板,执行 Preferences: Open User Settings (JSON),加入:

1
2
3
{
  "chat.agent.sandbox.enabled": "on"
}

也可以在设置界面搜索 chat.agent.sandbox.enabled,选择 on。新建一个 Copilot Agent 会话后再验证,不要只看旧会话的状态。

沙箱是按执行主机解析的。远程会话应该在远程主机对应的 VS Code 设置中配置,组织策略也可能覆盖本地设置。

3.2 用 /sandbox policy 查看有效策略

在 Copilot 会话输入:

1
/sandbox policy

VS Code 会生成 sandbox-policy.md,其中包括:

  • 执行主机和操作系统;
  • 沙箱是否启用;
  • 使用的系统实现;
  • 文件系统的读写、只读和拒绝路径;
  • 网络访问及域名策略;
  • 组织策略和运行时默认值。

这是排障时最有价值的证据。设置文件只能说明“你想配置什么”,策略报告才能说明“当前会话最终得到什么”。改完设置后重新运行一次;报告会更新为该会话的最新状态。

4. 遇到拦截时,按这个顺序排查

不要一看到拦截就关闭沙箱。建议按下面的顺序处理。

第一步:识别拦截类型

先看报错里涉及的资源:

现象 优先检查
Permission denied、无法读写某个目录 文件系统路径和路径优先级
Could not resolve host、下载包失败 allowNetwork、允许/拒绝域名
MCP 或语言服务器无法启动 对应服务器是否纳入沙箱、执行主机依赖
Git push 或 gh 认证失败 Git/GitHub 凭据代理和 CA 信任
提示缺少 bwrap、slirp4netns 等 远程执行主机的系统依赖
出现 Allow Outside Sandbox 沙箱内策略阻止了命令,正在请求一次回退

然后运行 /sandbox policy,确认不是“看错了设置作用域”。

第二步:给资源加最小权限

如果任务只需要访问一个构建目录,就只授权那个目录;如果只需要访问一个 API,就只允许那个域名。不要用“允许整个主目录”和“允许所有网络”来掩盖定位问题。

第三步:确认组织策略

带有“可由组织策略配置”的设置,可能被管理员锁定或收紧。此时本地 settings.json 不能放宽限制,需要让管理员调整 Copilot managed settings。

第四步:最后才考虑沙箱外执行

chat.agent.sandbox.allowUnsandboxedCommands 默认是 true,表示 Agent 可以在沙箱内失败后请求你批准在沙箱外运行。沙箱外运行会移除该操作的文件系统和网络限制,因此只应在以下条件同时满足时批准:

  1. 你理解命令会做什么;
  2. 命令来源可信;
  3. 你确认沙箱策略本身无法满足任务;
  4. 该操作不包含不必要的破坏性命令、凭据操作或不受控脚本。

如果设置为 false,界面不会提供 Allow Outside Sandbox,不符合沙箱策略的命令会直接失败:

1
2
3
{
  "chat.agent.sandbox.allowUnsandboxedCommands": false
}

5. 文件系统配置:读写、只读、拒绝

工作区当前目录会自动获得读写访问。额外路径通过 chat.agent.sandbox.fileSystem.userConfiguredPaths 配置:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
{
  "chat.agent.sandbox.fileSystem.userConfiguredPaths": {
    "readwritePaths": [
      "/Users/me/projects/build-output"
    ],
    "readonlyPaths": [
      "/Users/me/shared/source"
    ],
    "deniedPaths": [
      "/Users/me/private-data"
    ]
  }
}

三类路径的含义是:

  • readwritePaths:允许读写;
  • readonlyPaths:允许读取,但禁止写入;
  • deniedPaths:完全拒绝访问。

如果同一路径出现在多个数组中,优先级是:

1
deniedPaths > readonlyPaths > readwritePaths

allowDevToolAccess 的取舍

chat.agent.sandbox.fileSystem.allowDevToolAccess 默认是 true。它会自动授予常用开发工具目录、工具链目录、开发工具配置和缓存的读取权限,并允许访问共享构建缓存。这样能减少 Node、Python、Git 等工具在沙箱内失效的情况,但也可能让工具配置中的 registry token 等敏感信息更接近 Agent 进程。

更严格的配置可以关闭自动授权,再按任务需要补充路径:

1
2
3
{
  "chat.agent.sandbox.fileSystem.allowDevToolAccess": false
}

6. 网络配置:允许出站不代表允许所有目标

网络相关设置如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
{
  "chat.agent.sandbox.network.allowNetwork": true,
  "chat.agent.sandbox.network.allowLocalNetwork": false,
  "chat.agent.sandbox.network.allowedDomains": [
    "api.github.com",
    "registry.npmjs.org"
  ],
  "chat.agent.sandbox.network.deniedDomains": [
    "example.com"
  ]
}
  • allowNetwork:是否允许出站网络;
  • allowLocalNetwork:是否允许访问局域网和本机网络服务,默认 false;
  • allowedDomains:允许的网络目标;
  • deniedDomains:明确拒绝的网络目标。

实际使用时,可以先保持 allowNetwork: true,再以 allowedDomains 收窄范围。网络权限不只是“读取网页”:允许访问的服务可能接受写操作,也可能接触工作区内容或凭据,所以域名白名单应按任务建立,而不是长期使用通配式放行。

Windows 上还有一个常见陷阱:代理、主机名限制或凭据掩码可能需要沙箱访问本机代理监听端口。这时 allowLocalNetwork 必须为 true,否则命令可能还没开始就无法启动。只有确实使用这类代理时才打开它。

7. MCP、语言服务器和凭据

沙箱不仅影响终端:

1
2
3
4
5
6
{
  "chat.agent.sandbox.mcpServers": true,
  "chat.agent.sandbox.lspServers": true,
  "chat.agent.sandbox.credentials.authenticategit": true,
  "chat.agent.sandbox.credentials.authenticategh": true
}
  • mcpServers:是否将 Agent Host 启动或管理的 MCP Server 放入沙箱;
  • lspServers:是否将语言服务器放入沙箱;
  • authenticategit:是否为沙箱内 HTTPS Git 操作提供 Git 认证;
  • authenticategh:是否为沙箱内 gh 命令提供 GitHub 账户认证。

这些选项默认都是 true。如果任务不需要推送代码、创建 PR 或调用 GitHub API,可以关闭对应凭据能力,缩小影响范围:

1
2
3
4
{
  "chat.agent.sandbox.credentials.authenticategit": false,
  "chat.agent.sandbox.credentials.authenticategh": false
}

注意,这里的服务器控制只覆盖 Agent Host 管理的进程。你从系统终端独立启动的服务器,不会因为这些设置自动进入沙箱。

8. 证书错误和依赖问题怎么处理

8.1 Linux:在真正运行 Agent 的环境里安装依赖

Debian/Ubuntu 示例:

1
2
sudo apt-get update
sudo apt-get install bubblewrap slirp4netns util-linux iptables

Fedora、Arch 等发行版使用各自包管理器安装同类组件。除了软件包,还要确认:

  • bwrap 版本至少为 0.5.0;
  • slirp4netns 可用;
  • unshare、nsenter 来自符合要求的 util-linux;
  • iptables、ip6tables 及 restore 命令可用;
  • 用户和网络 namespace 未被环境禁用;
  • /dev/net/tun 具备所需读写能力。

容器或企业环境即使装了软件包,也可能因为内核能力被禁用而失败。此时需要调整容器运行参数或请管理员处理,而不是反复安装。

8.2 macOS 和 Windows:先更新系统

macOS 不需要额外沙箱包,优先安装系统更新。Windows 也没有单独的沙箱安装包,应安装符合文档要求的 Windows 11 更新并重启。

8.3 Sandbox trusted CA is not installed

启用凭据掩码时,Copilot 可能通过本地凭据代理连接批准的服务。代理需要用自己的 CA 证书与工具建立 TLS 连接,因此依赖操作系统证书存储的工具可能报 HTTPS 或认证错误。

这不代表所有沙箱命令都必须安装 CA;只有依赖系统证书存储、且需要通过凭据代理访问服务的工具才可能需要。按 VS Code 的系统提示安装对应 CA,并只在可信机器上这样做。

9. 一套可直接采用的配置模板

下面是一个偏保守、适合个人项目的起点:允许常规联网,但只声明必要域名;限制额外目录;不允许自动回退到沙箱外。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
{
  "chat.agent.sandbox.enabled": "on",
  "chat.agent.sandbox.allowUnsandboxedCommands": false,
  "chat.agent.sandbox.network.allowNetwork": true,
  "chat.agent.sandbox.network.allowLocalNetwork": false,
  "chat.agent.sandbox.network.allowedDomains": [
    "api.github.com",
    "github.com",
    "registry.npmjs.org",
    "pypi.org"
  ],
  "chat.agent.sandbox.network.deniedDomains": [],
  "chat.agent.sandbox.fileSystem.userConfiguredPaths": {
    "readwritePaths": [
      "/Users/me/.cache/my-build"
    ],
    "readonlyPaths": [
      "/Users/me/shared/schemas"
    ],
    "deniedPaths": [
      "/Users/me/private-data"
    ]
  },
  "chat.agent.sandbox.fileSystem.allowDevToolAccess": true,
  "chat.agent.sandbox.mcpServers": true,
  "chat.agent.sandbox.lspServers": true,
  "chat.agent.sandbox.credentials.authenticategit": true,
  "chat.agent.sandbox.credentials.authenticategh": false
}

把 /Users/me 替换为执行主机上的真实路径。远程会话不要直接复制本机路径。

10. 最后的检查清单

当 Copilot Agent 报告“命令被拦截”时,可以按下面的清单快速处理:

  1. 当前会话运行在本机、WSL、容器还是远程主机?
  2. /sandbox policy 是否显示沙箱已启用,实际策略是什么?
  3. 被拦截的是路径、域名、本地网络、MCP/LSP,还是系统依赖?
  4. 是否只需要添加一个目录或一个域名,而不是关闭沙箱?
  5. 是否被组织策略锁定?
  6. 是否真的需要 Git/GitHub 凭据?
  7. 是否能用一次性、可审查的沙箱外批准替代永久放宽?
  8. 修复后是否重新运行了原始命令,并再次查看策略报告?

沙箱的价值不在于让 Agent “什么都不能做”,而在于把“能做什么”变成可见、可配置、可审查的边界。把权限配置成任务需要的最小集合,通常比遇到问题后直接选择 Allow Outside Sandbox 更稳定,也更安全。

参考资料