← 返回目录

第 1 卷

第 1 / 4 卷日期:

张嘉熙 · DeepSeek Harness 前沿工程实践

图 1-1
图 1-1
图 1-2
图 1-2
图 1-3
图 1-3

你好,我是张嘉熙。

上一讲结尾我们把“程序执行本身的隔离”留成了另一道题。这一讲我们就来讲它,不过得先打个预防针:上一讲的 worker 线程只是“围住”,算不上安全边界,这一讲的进程沙箱同样不是

强隔离。

但开头得先破一个误解。说到“沙箱”,很多人脑子里浮现的是 Docker、虚拟机。不过这俩压根不是一回事:虚拟机自带内核,是真的“另一个世界”;Docker 用的仍是宿主内核,只是拿

namespace 把进程树、挂载点、网络这些视图隔开了,内核还是共享的那一个。

而 dsh 的进程沙箱比 Docker 还要再弱一档。官方对它的概括是:把同世界的子进程 argv (也就是要跑的那条命令)包进一层文件效果策略。同世界是说它与宿主共享文件系统和内

核,没被挪进另一个世界;文件效果划的是管辖边界:它只管对文件系统的改动,在这个范围内具体约束的就是能往哪儿写。重点在子进程:被约束的是一个个被启动起来的子进程,不是

关于环境:本讲新增三个包——@deepseek-ai/dsh-sandbox(seam 定义)、 @deepseek-ai/dsh-sandbox-local(本地实现)、@deepseek-ai/dsh-

sandbox-policy(策略解析),已加入本项目的 package.json,npm install -- legacy-peer-deps 装上即可。

关于示例平台:这一讲的运行输出来自 macOS。在 Linux 上你会看到 bwrap 或 Landlock,在 Windows 上会看到 ACL runner——机制不同,结论一致。想在一台机器上

看全三个平台的表现,跑 npm run start:ch07:platforms。

沙箱管什么,不管什么

它只管对文件系统的改动,约束程度分三种模式:

模式能往哪儿写典型用途
read-only只有/dev/null这一个必需的“下水道”只读探索、搜索、跑
workspace-write再加上工作区根目录,以及提供方承诺的临时区正常的编码任务
danger-full-access不限制显式提权后的重试

表格里冒出个新词——提供方。沙箱是分两层做的:一层只定规矩(要包装 argv、要报告执行结果,至于怎么做它不管),真正把规矩变成现实的,是另一个包,就是本讲开头装的

@deepseek-ai/dsh-sandbox-local。用哪个 runner、怎么包装 argv、执行得怎么样,全由它说了算;消费方只拿结果,不关心内部。所以表里说的“提供方承诺的临时区”,就是它

答应给你的那块可写地方。

表头里的“能往哪儿写”是广义的写:创建、删除、重命名、改属性,凡是让文件系统发生变化的操作都算,不只是往文件里写数据。删个文件、给文件改个时间戳,一样受这张表约束。

会一直见到它)。

这里值得停一下:在 dsh 里,“不套沙箱”只有一条来路,就是策略被显式指定成了这个模式(比如用户批准了一次提权重试)。它不是“沙箱没配好、干脆裸跑”的兜底路径,真到沙箱不

可用时,提供方会直接抛异常,也就是后面要讲的“失败关闭”。所以每一次没套沙箱的执行,都能在策略里追溯到出处。

而不在这个词汇表里的东⻄,得记牢:

不管网络:沙箱里的进程照样能联网、照样能往外发数据。

不管进程可见性:它能看见宿主的其他进程。

也不管读:它只拦写、不拦读——宿主上的密钥、登录凭据,进程照样读得到。

换句话说,这是一个文件效果围栏,不是一个通用沙箱。把它当后者用,就会在“为什么它没拦住网络请求”上栽跟头。

沙箱怎么用:命令一个字不改,前面加半截

用法就一句话:

复制代码 1const confined = ctx.sandbox.confine(argv, policy)

argv 就是一条命令拆成的数组,第一个元素是要运行的那个程序(严格说是程序名,比如 bash,真正的文件路径由系统去查),后面是传给它的参数。注意它不是 shell 字符串:要

跑 shell,得传 ['bash', '-c', command],而不是 'bash -c ...'。这句约束看着琐碎,其实是安全前提:一旦传字符串,谁来解释、边界在哪儿就全乱了。第二个参数 policy

是第一节说的模式加工作区根目录,它怎么定,下一节单独讲。

全站分卷索引 · 4 卷
  1. 1第 1 卷
  2. 2第 2 卷
  3. 3第 3 卷
  4. 4第 4 卷