DeepSeek Harness plugin

dsh-seatbelt-sandbox

Seatbelt (libsandbox) sandbox provider for the DeepSeek Harness sandbox seam on macOS: a cordis plugin that replaces @deepseek-ai/dsh-sandbox-local's seatbelt rung via a prebuilt seatbelt-run

Jump to install

Source facts

Repository
drscrewdriver/dsh-seatbelt-sandbox
Latest update
Aug 20, 2026
Category
Models & Providers
GitHub stars
1
Format
plugin
Catalog evidence
Upstream dsh.bundle evidence
Evidence path
package.json#dsh.bundle
Checked against
0.1.0-rc.8
Upstream check date
2026-08-20

This evidence comes from the upstream catalog. This site has not installed, run, or security-reviewed the plugin.

Install

Start with a prompt that asks an agent to review the GitHub repository and source. Switch to the command if you want to install it yourself.

Copy this prompt into DSH, Codex, or another agent and ask it to review the GitHub repository and source first.

Do not install or run any commands yet. Read this plugin's GitHub repository, README, and relevant source code. Then answer the questions below clearly and directly so I can decide whether it fits my needs:

1. What is this plugin, and what problem does it solve?
2. Who is it for, and what are its typical use cases?
3. How is it used after installation? Include one minimal example.
4. What known limitations or privacy, security, compatibility, or maintenance risks does it have?
5. Give a clear recommendation: recommend, conditionally recommend, or do not recommend, with reasons.

Distinguish statements documented by the repository, inferences from source code, and unknowns. If evidence is insufficient, say so explicitly. Do not guess or simply repeat the README.

GitHub: https://github.com/drscrewdriver/dsh-seatbelt-sandbox
Plugin: dsh-seatbelt-sandbox
Author: drscrewdriver

Check the source files

Read the README and other files from this plugin directory before installing.

File explorer3 files
README.mdSource · read only

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-<arch>/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 PID> && 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<github-owner> 为你的 GitHub 用户名,推送后替换): > > ``sh > npm install <github-owner>/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-<arch>/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](examples/cordis.yml)。消费方(@deepseek-ai/dsh-bash-sandbox@deepseek-ai/dsh-fs-sandbox 等)只依赖 ctx.sandbox 服务(服务注入,与插件 id 无关),对后端实现零感知。

loaderPath 仅当二进制未随包分发(例如单独拷贝到固定路径、或需要跨架构指定)时使用;缺省时 launcherPath()process.platform + process.arch 解析包内 bin/darwin-<arch>/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 <当前 dsh web 的 PID>    # 如: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" } }filescordis.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 <profile-file> [--] <cmd> <args...>
seatbelt-run --self-test
  • profile 走文件传递(规避 ARG_MAX);可选 -- 分隔符与 dsh confine 惯例对齐,且与 inferglow seatbelt-loader <profile-file> <cmd> 契约兼容(无 -- 形态同样可用,二进制可互换)。
  • 失败统一退出 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,更强)
enforcementfullfull(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.tswritableRoots / 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.mjstests/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 真实内核 e2e17/17
装配层examples/verify-dsh-boot.mjs:复用 dsh CLI runProfile(与 dsh web 同一 boot 路径)真实 boot8/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](docs/ablation.md)):PATH 遮蔽模拟 sandbox-exec 归档后——本插件 8/8 全过、官方 rung 直接 SANDBOX_UNAVAILABLE fail-closed 拒绝一切命令;含可复现步骤与手动两阶段对照(卸载+遮蔽 → 报错 / 安装+遮蔽 → 正常)。

发布前验收清单(macOS)

# 1. 构建二进制 + 自检
npm run build:native                                  # bin/darwin-<arch>/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

推送到 GitHub

# 1. 在 GitHub 新建仓库(建议同名 dsh-seatbelt-sandbox)
# 2. 关联并推送(master 分支):
git remote add origin git@github.com:<your-org>/dsh-seatbelt-sandbox.git
git push -u origin master
# 3. 推送后替换 README/示例中的 <github-owner> 为实际用户名
# 4. 发布 npm 前:补 package.json 的 repository 字段,并完成「发布前验收清单」

参考

  • .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-trafficDSH Web GUI 忙时输入队列:三档交通管制,拖拽重排,会话冻结
dsh-thinking-levels逐轮 reasoning_effort 控制:Auto 智能调度或手动固定档位
dsh-seatbelt-sandboxmacOS Seatbelt 沙箱适配器:libsandbox 原生 loader,接替弃用的 sandbox-exec
dsh-switch-search侧边栏会话搜索增强:标题/内容切换,按用户/回复/工具筛选