Replies: 2 comments
|
I generally support this direction. We should not overlook the security risk created by over-privileged third-party stdio MCP server processes. Call-time approval does not constrain what a server may do during startup, initialization, background activity, or through its child processes, so enforceable launch-time isolation for Host-spawned stdio servers would provide valuable defense in depth. I only want to extend the discussion with one additional consideration. If multiple Sessions require different process-level permissions for the same stdio MCP server—for example, a code-review Session permits only read access to the workspace while an implementation Session requires write access, or an ordinary Session permits network access while a controlled Session explicitly forbids it—then, if both Sessions must be able to use the server while preserving their respective security boundaries, the same stdio MCP server configuration would necessarily require multiple process instances running under different isolation profiles. This would increase the complexity of Host-side instance addressing, lifecycle management, reconnection, status reporting, logging, and tool-snapshot ownership. It could also expose implicit single-instance assumptions or insufficient cross-process synchronization in third-party servers. For example, two processes might concurrently read and write the same JSON, JSONL, SQLite, or cache file while the server implements only an in-process lock, resulting in lost updates or corrupted state. They might also contend for a fixed port, PID/lock file, browser profile, database write lock, or another exclusive resource, or run migrations, file watchers, scheduled synchronization, and other background work twice. The official memory server's process-local mutation queue and read-modify-replace persistence pattern illustrates why sharing one storage path across processes still requires additional cross-process coordination: memory server implementation. A simpler alternative is to give each server one fixed launch policy that is independent of any Session. Sessions would only decide whether they accept those execution facts and may invoke the server's tools. If a Session does not accept the server's process-level permissions, those tools would be unavailable to that Session. However, if the product intends to provide per-Session or per-profile process confinement, the multi-instance problem cannot be avoided. Therefore, in addition to a per-server sandbox flag or launch policy, I think the design should define instance-sharing semantics such as AI assistance disclosure: Drafted by me; OpenAI Codex verified and expanded the content. 中文我总体上支持这一做法。不能忽视第三方 stdio MCP server 进程权限过宽所带来的安全风险:调用层面的审批并不能约束服务器在启动、初始化、后台任务或子进程中执行的行为,因此为 Host-spawned stdio server 增加可强制执行的启动期隔离,是有价值的纵深防御。我在这里只做一点延伸思考。 如果多个 Session 对同一个 stdio MCP server 进程有不同的权限要求——例如代码审查 Session 只允许读取工作区,而实施 Session 需要写权限;或者普通 Session 允许联网,而受控 Session 明确禁止联网——那么在两个 Session 都必须使用该服务器、同时又必须维持各自安全边界的前提下,同一份 stdio MCP server 配置必然需要产生多个隔离策略不同的进程实例。 这不仅会提高 Host 后台组织和管理的复杂度,包括实例寻址、生命周期、重连、状态、日志和工具快照的归属,还可能暴露第三方 stdio MCP server 自身隐含的“单实例”假设或跨进程同步缺陷。例如,两个进程可能同时读写同一个 JSON、JSONL、SQLite 或缓存文件,而服务器只实现了进程内锁,最终造成更新丢失或数据损坏;也可能争用固定端口、PID/lock 文件、浏览器 profile、数据库写锁等独占资源,或者重复运行 migration、文件 watcher、定时同步等后台任务。官方 memory server 的进程内 mutation queue 和 read-modify-replace 持久化方式,就能说明为什么多个进程共享同一存储路径时仍然需要额外的跨进程协调:memory server implementation。 当然,另一种更简单的模型是:每个 server 只有一份固定的、独立于 Session 的 launch policy;Session 只决定是否接受该执行事实并调用其工具。如果某个 Session 不接受该 server 的进程权限,就不向该 Session 暴露工具。但如果产品确实希望提供 per-Session 或 per-profile 的进程级隔离,那么多实例问题就无法回避。 因此,除了 per-server sandbox flag 或 launch policy,我认为还需要明确实例共享语义,例如 AI assistance disclosure: 我起草,OpenAI Codex 核实和丰富内容。 |
|
Agreed, and I think we're describing the same thing: what I had in mind is your simpler model, one fixed launch policy per server, declared in its config and independent of the Session, so a Session either accepts those execution facts or doesn't see the tools. Per-Session confinement was never on the table here; my reason was that the Session profile is the wrong constraint for what most servers legitimately need, and your multi-instance point is a second, harder reason to keep it off. The one thing I'd take from your note is the typed |
Uh oh!
There was an error while loading. Please reload this page.
#3629 settled that a Session has one revisioned
SandboxPolicyand that Runtime evaluates ordinary tool calls before first dispatch. One execution path still sits outside that picture, and I'd like to check whether it belongs inside it.Observation
McpManager.openClient(packages/mcp/src/index.ts:1115) constructsStdioClientTransportdirectly, and nothing underpackages/mcp/srcreferences the sandbox. So in a Session where Bash is confined by Seatbelt or bwrap — and fails closed when no backend is available — a stdio MCP server named in the same config runs as an ordinary child of Runtime Host: full user identity, full filesystem, full network. Its tools are then offered to the model.Two things are better than that summary suggests and should stay as they are:
buildStdioEnvironment,index.ts:2409);packages/runtime/src/mcp-tools.ts:147-157).Neither confines the process. The call is gated; the thing that could do anything is not.
Why the existing threads don't cover it
request_sandbox_boundary, says not to introduce a universal capability language for MCP, and — explicitly — says not to claim the local process sandbox contains native or remote tools. So the gap was known and accepted at the time. What feat: replace per-tool approvals with sandbox boundaries #1564 did not decide is whether a Host-spawned server process may be launched under the Session's sandbox backend. That is a launch-time isolation choice for one child process, the same kindfilesystem-workeralready makes for itself — not a capability language for what the server's tools may do.serverId + toolName. It does not touch where a Host-spawned server process runs.Question
Should sandboxed launch be a per-server declared capability, rather than something inherited from the Session profile? The Session profile is the wrong constraint for many servers — they legitimately need network and out-of-workspace paths — but "no constraint at all" is the current default.
Concretely: route
openClient's{ command, args, cwd, env }through the existingSandboxManager.transform, the waypackages/runtime/src/filesystem-worker/client.ts:444already does for its own long-lived helper, behind an opt-in per-server flag; and when the platform cannot enforce the declared isolation, fail closed with a typed unsupported-isolation error instead of a bare spawn. That would also giveToolExecutionIsolation(packages/core/src/permission.ts:111) its first non-'none'value in practice.I'm not attached to the shape — mainly asking whether this is in scope for the post-#3629 SandboxPolicy work, or deliberately out.
中文
#3629 已经确定:一个 Session 有唯一的带 revision 的
SandboxPolicy,Runtime 在工具首次执行前完成判断。但有一条执行路径目前在这个图之外。McpManager.openClient直接构造StdioClientTransport,packages/mcp/src里没有任何地方引用 sandbox。于是在一个 Bash 被 Seatbelt/bwrap 约束、后端不可用时 fail closed 的 Session 里,同一份配置里的 stdio MCP server 却以 Runtime Host 普通子进程的身份运行——完整用户身份、完整文件系统、完整网络。两处现状是好的、应保留:stdio 环境是白名单;托管边界下的 MCP 工具调用已经需要网络审批。但两者都不约束进程。
#1564 把 MCP 的强制归属定为"工具暴露 + server/connector 自身的 scope",禁止 MCP 使用
request_sandbox_boundary,明确不为 MCP 引入通用能力语言,并且明说"不要声称本地进程沙箱覆盖了原生或远程工具"——所以这个缺口当时是已知且接受的。它没有决定的是:Host 自己派生的 server 进程能否在 Session 的沙箱后端下启动。这是对一个子进程的启动期隔离选择(filesystem-worker已经这么做了),不是描述其工具能做什么的能力语言;#4012 处理的是 Desktop 侧 MCP 的调用时 Session Grant,不涉及 Host 派生的 server 进程跑在哪。想问的是:沙箱化启动是否应该成为每个 server 自己声明的能力,经现有
SandboxManager.transform编译(filesystem-worker/client.ts:444已经这么做了),平台无法强制时以带类型的错误 fail closed,而不是裸 spawn?主要想确认这是否在 #3629 之后的 SandboxPolicy 工作范围内。
AI assistance disclosure: source verification and drafting assisted by Claude; reviewed by me.
All reactions