DeepSeek Harness Hub
← 返回列表

macOS 沙箱适配器drscrewdriver/dsh-seatbelt-sandbox

DeepSeek Harnessspec-screened在 GitHub 查看 ↗
⚠ 装前注意

dsh-seatbelt 方面沙箱增强尝试使用非exec工具直接对接系统seatbelt相关api

基本兼容但装前注意:未发布到 npm registry,仅可从源码安装 · 最近上游提交 2026/9/17 · 已提供中文文档
综合分
30.7
GitHub 分
30.7
用户评分
★ Stars
1
周下载量
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add drscrewdriver/dsh-seatbelt-sandbox
未发布到 npm registry,仅可从源码安装,改用 GitHub 源安装
数据截至 2026/9/18(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
安装兼容性检查⚠ 装前注意

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

npm 包dsh-seatbelt-sandbox(未发布到 npm,仅可源码安装)
Node 引擎要求 >=20 · 基线 Node 22.19 满足
dsh CLI 依赖未声明 dsh 版本约束
入口文件main/exports/bin 已声明

未发布到 npm registry,仅可从源码安装

验证方式:npm registry 存在性 + package.json 静态校验 · 最后验证 2026/9/19 10:25:34

依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-sandbox
用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动

README

dsh-seatbelt-sandbox

macOS Seatbelt(libsandbox)沙箱适配器,为 DeepSeek Harness(dsh)提供 cordis 插件形态的 seatbelt rung 替换:部署时在 cordis.yml 里把 sandbox 插件从 @deepseek-ai/dsh-sandbox-local 换成 dsh-seatbelt-sandbox,即可让 dsh 的 macOS 沙箱从 Apple 弃用的 sandbox-exec CLI 切换到直接调用私有 libsandbox API 的自带 loader——无需修改 dsh 源码、无需提 PR。

当前状态(筹备阶段)

| 项 | 状态 |
|----|------|
| 单元测试(SBPL 方言 / argv 组装 / 缓存 / 探测 / fail-closed) | ✅ 12/12 通过(macOS arm64 实测) |
| tsc 严格模式编译 | ✅ 通过 |
| macOS 二进制构建(npm run build:native) | ✅ 已完成(macOS arm64;bin/darwin-arm64/seatbelt-run 34KB 有效 Mach-O) |
| macOS 真实内核 e2e(deny-write / workspace-write / 坏 profile 125) | ✅ 5/5 通过(macOS arm64 真实内核断言) |
| dsh 装配集成(web profile 真实 boot + [sandbox: file access denied] 归因) | ✅ 已验证(macOS arm64 实测:examples/verify-dsh-boot.mjs 8 项 + verify-integration.mjs 4 项全过) |
| npm 发布 | ⏳ 未发布(dsh-seatbelt-sandbox 尚未 publish) |
| darwin-x64 二进制 | ⏳ 未构建(arm64 优先,x64 需 Intel macOS 环境) |

代码与测试基于 dsh 源码逐行核实(landlock-run 先例形态、confine() 契约、SBPL 方言),macOS arm64 上已通过全部 25 项测试(12 单元 + 5 e2e + 8 真实 boot 装配)。在完成下方「发布前验收清单」前,请勿用于生产部署。

快速开始(筹备阶段)

前置条件

- macOS 主机(arm64;x64 需先补 darwin-x64 二进制,见状态表)
- 已安装 dsh CLI(npm i -g @deepseek-ai/dsh)与 pnpm(dsh plugin 命令依赖 pnpm)
- Node.js ≥ 20;macOS Command Line Tools(含 clang,build:native 需要)
- 仅 macOS 部署使用;Windows/Linux 请保留官方 sandbox-local

1. 获取源码
git clone git@github.com:drscrewdriver/dsh-seatbelt-sandbox.git && cd dsh-seatbelt-sandbox

2. 安装依赖 + 构建(git 安装后 node_modules/、lib/、bin/ 三者全部缺失,缺一不可)
npm install                 # node_modules/
npm run build               # lib/(tsc 编译;缺了它插件 main 指向的 lib/index.js 不存在,加载直接失败)
npm run build:native        # bin/darwin-/seatbelt-run(含 Mach-O 校验)
./bin/darwin-$(uname -m)/seatbelt-run --self-test && echo OK   # 自检:libsandbox 可用

3. 完整测试(12 单元 + 5 macOS e2e,无 skip)
npm test

4. 接入 dsh(完整步骤见下节「dsh plugin 命令组装」)
dsh plugin --profile web add /absolute/path/to/dsh-seatbelt-sandbox
(或 GitHub 直装:dsh plugin --profile web add github:drscrewdriver/dsh-seatbelt-sandbox#master)
dsh web --dump-config | grep -B1 -A3 'sandbox-seatbelt'  # 确认官方行 disabled + 本插件新行
node examples/verify-dsh-boot.mjs                         # 真实 boot 8 项断言,全绿即装配正确
kill  && dsh web                  # 重启使新装配生效(必做:运行中实例不热载 bundle 层)

为什么需要它

Apple 自 macOS 10.10 起弃用 sandbox-exec CLI,未来系统版本可能移除;但底层 libsandbox.1.dylib 的私有 API(sandbox_init / sandbox_free_error)仍是 macOS 安全架构核心(App Sandbox、sandboxd、Chromium/Firefox 都在生产环境直接调用)。任何需要 macOS 沙箱的语言生态都应基于该 API 构建 loader 模式:

sandbox_init(profile)   ← 沙箱化当前进程(不可逆,仅一次)
execvp(cmd, argv)       ← 替换进程映像;沙箱是进程属性,跨 exec 保留

核心不变量:沙箱必须作用于最终运行目标命令的进程,且必须先于目标启动应用。

纯 JS 无法自做 loader(无内建 FFI、无 execve 原语、V8 运行时窗口大),因此本包采用 C11 原生 loader 二进制 + JS seam 结构——与 dsh 仓库内 native/landlock-run 先例同构。

架构

dsh-seatbelt-sandbox/
├── native/seatbelt-run/src/main.c  # C11 loader:dlsym libsandbox → execvp(唯一审计面)
├── src/
│   ├── sbpl.ts                     # SBPL profile 生成(复制 dsh roots.ts/profiles.ts 语义)
│   ├── loader.ts                   # launcherPath() / probe()(--self-test)
│   ├── provider.ts                 # SeatbeltSandboxProvider extends SandboxProvider
│   └── index.ts                    # 插件默认导出
├── bin/darwin-{arm64,x64}/         # 预编译二进制(macOS 上 npm run build:native 生成)
├── tests/                          # node:test 单元(任意平台)+ macOS e2e
└── examples/cordis.yml             # 部署装配示例

安装与构建

⚠️ 包尚未发布 npm。发布前请通过 git 安装或本地 npm pack:

npm install drscrewdriver/dsh-seatbelt-sandbox   # 或 npm pack 后安装 tarball

⚠️ GitHub 网络可达性:github: 直装需要能连通 github.com;网络受限时请先配置可用代理或镜像加速,否则 add 会在拉取阶段卡住。

三种安装方式的构建要求

| 安装方式 | 仓库自带 | 必须现场执行 |
|----------|----------|--------------|
| npm pack tarball / npm 发布 | lib/、bin/ 随包(files 声明) | 无(直接可用) |
| git 安装(dsh plugin add github:…) | 无(lib/、bin/、node_modules/ 均不入库) | npm install + npm run build + npm run build:native |
| 本地 path/link 安装(dsh plugin add /本地/路径) | 无(link 指向本地仓库) | 仓库侧先完成 npm install + npm run build + npm run build:native |

git 安装后的构建(缺一不可):
cd ~/.dsh/profiles/web/node_modules/dsh-seatbelt-sandbox
npm install
npm run build             # 编译 lib/(缺了它插件加载失败:main 指向 lib/index.js)
npm run build:native      # 生成 bin/darwin-/seatbelt-run

- 构建为 macOS-only(scripts/build.sh 在非 darwin 平台快速失败),使用系统自带 clang,无额外工具链。
- 二进制按架构分发:bin/darwin-arm64/ 与 bin/darwin-x64/,launcherPath() 按 process.platform + process.arch 解析;缺平台包时探测失败 → fail-closed(SANDBOX_UNAVAILABLE),绝不无约束直通。

部署装配(自托管 macOS)

⚠️ dsh 的 patch 语义(dsh-app-boot applyEntryPatches):非 insert 行的 name 只做匹配检查、不能改名;insert 是追加;cordis loader 对重复 id 直接抛 TypeError: duplicate loader entry id。因此替换插件必须「禁用官方行 + 追加新 id 行」两步(见下方),直接写 - id: sandbox / name: dsh-seatbelt-sandbox 会被 name 匹配检查跳过、不生效。

cordis.patch.yml —— 唯一改动:禁用官方 sandbox 行 + 追加本插件行
- id: sandbox
name: '@deepseek-ai/dsh-sandbox-local'   # name 仅作匹配检查,必须与官方行一致
disabled: true                          # 覆盖:官方行不加载
- insert:
- id: sandbox-seatbelt                # 必须与官方行 id 不同(loader 禁止重复 id)
name: dsh-seatbelt-sandbox
config 全部可选:
loaderPath: /absolute/path/to/seatbelt-run
probeTimeoutMs: 5000
sandbox-policy / bash / fs-sandbox 等其余插件与配置不动

完整示例见 examples/cordis.yml。消费方(@deepseek-ai/dsh-bash-sandbox、@deepseek-ai/dsh-fs-sandbox 等)只依赖 ctx.sandbox 服务(服务注入,与插件 id 无关),对后端实现零感知。

loaderPath 仅当二进制未随包分发(例如单独拷贝到固定路径、或需要跨架构指定)时使用;缺省时 launcherPath() 按 process.platform + process.arch 解析包内 bin/darwin-/seatbelt-run。

沙箱粒度配置(sandbox-policy,非本插件)

- 默认 workspace-write:workspace 内可写、外部写被内核拒(operation not permitted)、/tmp 与用户 temp 区授权;read-only 全只读;danger-full-access 无沙箱。
- 运行时经环境变量切换(需重启):DSH_PERMISSION_MODE=read-only|workspace-write|danger-full-access。
- 拒绝是预期行为:命令报 operation not permitted 或 UI 归因 [sandbox: file access denied …] 表示沙箱在工作,不是环境故障。

dsh plugin 命令组装(完整步骤)

自托管部署用 dsh CLI 的插件管理命令把本插件组装进 profile(macOS 主机):

1. 组装(GitHub 直装或本地路径,任选其一)
dsh plugin --profile web add github:drscrewdriver/dsh-seatbelt-sandbox#master
或本地路径(link 安装,改动即时生效):
dsh plugin --profile web add /Users/joshua/Desktop/dsh/dsh-seatbelt-sandbox

2. 确认 reconcile 成功:dependencies 与 dsh.profile.bundles 均应含 dsh-seatbelt-sandbox
cat ~/.dsh/profiles/web/package.json

3. 构建(仅 git 安装需要;本地 path 安装需仓库侧已构建好)
cd ~/.dsh/profiles/web/node_modules/dsh-seatbelt-sandbox
npm install && npm run build && npm run build:native

4. 确认组合树:官方 sandbox 行 disabled: true + 本插件新行(无重复 id)
dsh web --dump-config | grep -B1 -A3 'sandbox-seatbelt'

5. 装配验证(独立真实 boot,8 项断言;插件级 4 项断言)
node ~/.dsh/profiles/web/node_modules/dsh-seatbelt-sandbox/examples/verify-dsh-boot.mjs
node ~/.dsh/profiles/web/node_modules/dsh-seatbelt-sandbox/examples/verify-integration.mjs

6. 重启 dsh web —— 必做!运行中的实例不会热加载 bundle 层(HMR 只 watch 用户层 patch)
kill     # 如:lsof -nP -iTCP:3080 -sTCP:LISTEN 查 PID
cd  && dsh web

⚠️ 本地 path/link 安装时跑 verify-integration.mjs:该脚本 import 'dsh-seatbelt-sandbox' 从仓库自身 node_modules 解析,需先建自引用链接(cd  && ln -sf .. node_modules/dsh-seatbelt-sandbox);npm 包/git 真实安装无此问题。

⚠️ peer 依赖:插件 peerDependencies 为 @deepseek-ai/cordis 与 @deepseek-ai/dsh-sandbox(与 dsh 运行时同版本)。本地 link 安装时从仓库自身 node_modules 解析;git 安装时 pnpm 自动安装 peers;若 pnpm peers check 报缺,在 profile 下 dsh plugin --profile web add @deepseek-ai/cordis@^4.0.1 @deepseek-ai/dsh-sandbox@^0.1.0-rc.6。

回滚:dsh plugin --profile web remove dsh-seatbelt-sandbox 后重启,即恢复官方 sandbox-local。

✅ 已落地(Issue #1 前置条件):
1. package.json 已声明 "dsh": { "bundle": { "patch": "./cordis.patch.yml" } }(files 含 cordis.patch.yml)—— dsh plugin reconcile 据此把包加入装配层;
2. cordis.patch.yml 按 dsh patch 语义写成「禁用官方 sandbox 行 + insert 追加 dsh-seatbelt-sandbox 行(新 id sandbox-seatbelt)」;
3. 注意:早期提交(0bd8b63 之前)的 patch 是纯 insert 追加同 id 行,会导致 boot 抛 duplicate loader entry id——请使用本仓库最新提交。

loader CLI 契约

seatbelt-run  [--]
seatbelt-run --self-test

- profile 走文件传递(规避 ARG_MAX);可选 -- 分隔符与 dsh confine 惯例对齐,且与 inferglow seatbelt-loader   契约兼容(无 -- 形态同样可用,二进制可互换)。
- 失败统一退出 125(对齐 dsh landlock launcher 约定),stderr 前缀 seatbelt-run: ;沙箱 denial 是内核方言 operation not permitted,与 loader 失败可区分。
- --self-test 应用空 profile (version 1),退出 0 表示 libsandbox API 可用——插件的功能探测。

与官方 seatbelt rung 的行为差异

| 维度 | 官方 @deepseek-ai/dsh-sandbox-local | 本插件 |
|------|--------------------------------------|--------|
| 执行器 | sandbox-exec CLI(已弃用) | seatbelt-run(直调 libsandbox,跨生态共享契约) |
| 探测 | 真实 read-only profile + true | --self-test(空 profile,与 inferglow/Python 生态一致) |
| denial 方言 | operation not permitted | 相同 |
| runner 失败签名 | sandbox-exec: (无退出码门控) | seatbelt-run:  + allowedExitCodes: [125](exit-gated,更强) |
| enforcement | full | full(SBPL deny file-write* 按构造保证) |
| 探测失败 | fail-closed SANDBOX_UNAVAILABLE | 相同 |
| SBPL 生成 | seatbeltProfileArgs(dsh 内部) | 本包 sbpl.ts(复制上游语义,方言测试 pin 等价) |
| profile 文件 | 内联 -p 传递 | 临时文件(provider 级缓存 + dispose 清理) |

契约跟踪责任(升级注意)

本插件通过 peerDependencies 锁定 @deepseek-ai/cordis 与 @deepseek-ai/dsh-sandbox。dsh 上游若演进 ConfinedArgv / SandboxPolicy / SandboxProvider 契约,需同步更新 src/provider.ts(契约变化集中于该单文件);src/sbpl.ts 的 writableRoots / seatbeltProfileText 语义来自 dsh 的 roots.ts / profiles.ts(BSD-3-Clause,来源已标注),上游变更时同步镜像并由 tests/sbpl.test.mjs 的方言断言兜底。

测试

npm test          # 单元测试任意平台可跑;macOS e2e 自动跳过
npm run build:native && npm test   # macOS 上跑完整套件(真实内核双向断言)

- 单元(tests/sbpl.test.mjs、tests/provider.test.mjs):SBPL 方言、argv 组装、profile 缓存/清理、探测缓存、fail-closed。
- macOS e2e(tests/seatbelt.e2e.mjs):read-only deny-write 不落盘 + operation not permitted、/dev/null 可写、workspace-write 双向断言、temp 区授权、坏 profile → 125 + seatbelt-run: 。
- 装配集成:examples/cordis.yml 替换后,ctx.sandbox.confine() 走新 provider,bash 沙箱的 [sandbox: file access denied …] 归因基于本插件的 denial 方言正确工作。

装配验证报告(macOS arm64,2026-08-17)

三层验证闭环,全部通过:

| 层 | 验证 | 结果 |
|----|------|------|
| 插件层 | npm test:12 单元 + 5 macOS 真实内核 e2e | 17/17 |
| 装配层 | examples/verify-dsh-boot.mjs:复用 dsh CLI runProfile(与 dsh web 同一 boot 路径)真实 boot | 8/8 |
| 会话层 | 在真实 harness 会话中由 agent 执行行为验证(工作区写/外部写被拒+文件未创建/temp 授权/只读正常,全程无 sandbox-exec 踪迹) | 4/4 |

装配层 8 项断言明细:ctx.sandbox 构造器为 SeatbeltSandboxProvider;confine 产出 [seatbelt-run, profileFile, --, ...argv] 且无 sandbox-exec;read-only 写被内核拒(operation not permitted)且文件未创建;workspace-write 内成功外被拒;消费方 ctx.shell(bash-sandbox)经本插件 denial 方言正确归因 denied=true / denied=false。

结论:插件在 macOS arm64 上理论可用——沙箱能力由 Apple 内置 seatbelt(内核强制)承担,本插件接管「策略 → SBPL profile → 送入内核」适配段(弃用 CLI → 直调 libsandbox),拦截由内核执行、归因由本插件保障。正式生产部署前仅剩 npm 发布与 darwin-x64 二进制两件事(见状态表)。

消融实验证据(docs/ablation.md):PATH 遮蔽模拟 sandbox-exec 归档后——本插件 8/8 全过、官方 rung 直接 SANDBOX_UNAVAILABLE fail-closed 拒绝一切命令;含可复现步骤与手动两阶段对照(卸载+遮蔽 → 报错 / 安装+遮蔽 → 正常)。

发布前验收清单(macOS)

1. 构建二进制 + 自检
npm run build:native                                  # bin/darwin-/seatbelt-run + Mach-O 校验
./bin/darwin-arm64/seatbelt-run --self-test && echo OK

2. 完整测试套件(真实内核断言,无 skip)
npm test                                              # 12 单元 + 5 e2e 全部通过

3. dsh 装配集成(dsh plugin --profile web add 后)✅ 已完成
- examples/verify-dsh-boot.mjs:真实 boot,8 项全过(装配/argv 形态/无 sandbox-exec/内核拒绝/workspace-write/消费方归因)
- examples/verify-integration.mjs:4 项全过(装配/read-only/workspace-write/fail-closed)
- loader 缺失时抛 SANDBOX_UNAVAILABLE(fail-closed)

4. 发布
npm pack && npm publish                               # 确认 tarball 含 bin/darwin-*/seatbelt-run

仓库结构约定(dsh 插件清单)
本仓库是可被 dsh plugin 识别与消费的标准 dsh 插件包,三处声明缺一不可:

| 文件 | 作用 |
|------|------|
| package.json → dsh.bundle.patch | 指向 cordis.patch.yml,dsh plugin reconcile 据此把本包加入装配层 |
| cordis.patch.yml | patch 语义本体(禁用官方 sandbox 行 + insert 追加本插件行) |
| dsh.plugin.json | 插件清单描述符:id / version / description.{en,zh} / engines.dsh / components.host |

- 本插件是纯 host 侧插件(无浏览器半边),因此 dsh.plugin.json 的 components 只有 host、没有 client,
package.json 的 dsh 也只有 bundle、没有 client。
- engines.dsh = >=0.1.0-rc.6,取值来自本包 peerDependencies 的 @deepseek-ai/dsh-sandbox: ^0.1.0-rc.6。
- dsh.plugin.json 与 cordis.patch.yml 均在 package.json 的 files 白名单内,随 npm 包一同分发。

参考

- .trae/specs/seatbelt-ts-adapter/(工作区根,三件套 spec/checklist/tasks)——需求规格(本实现为"插件方式"落地)
- dsh native/landlock-run——C11 loader + JS seam 的包形态先例
- dsh packages/sandbox/sandbox/src/{index.ts,roots.ts}、sandbox-local/src/profiles.ts——契约与 SBPL 语义来源
- inferglow sandbox/seatbelt_loader/——Go 生态同契约实现

drscrewdriver DSH Plugin Family

本项目是 drscrewdriver 维护的 DSH 插件系列之一。如果这个对你有用,其他插件多半也有用:

| 插件 | 一句话描述 |
|---|---|
| dsh-input-traffic | DSH Web GUI 忙时输入队列:三档交通管制,拖拽重排,会话冻结 |
| dsh-thinking-levels | 逐轮 reasoning_effort 控制:Auto 智能调度或手动固定档位 |
| dsh-seatbelt-sandbox | macOS Seatbelt 沙箱适配器:libsandbox 原生 loader,接替弃用的 sandbox-exec |
| dsh-search-index | 侧边栏搜索索引:标题搜索与内容搜索一键切换,自带独立索引,支持增量同步 |

上游仓库有新提交时邮件通知你(每天最多一封,无更新不打扰),随时一键退订。

💬 加入 DPharness 群聊

插件用法、部署报错、新插件第一时间同步——群里问,比一个人翻文档快。

点击加入 QQ 群
DPharness 群聊二维码,手机 QQ 扫码进群
扫码进群