dsh-perm-gate
已追加 cc-safety-net 风格的机械安全网规则,同时支持无模型、有模型辅助方式的安全审查,模式为自动审查、机械直通等。P0–P4 确定性优先权限门控,含 Permissive 档位、学习沉淀与审批历史 UI;凭据/受保护路径硬拒绝,内部只读工具自动放行。
安装
dsh plugin --profile web add dsh-perm-gate
沙箱测试结果
| 阶段 | 结果 |
|---|---|
| 1 安装 | ✗ |
| 2 列装 | ✗ |
| 3 挂载 | — |
| 4 启动 | — |
dsh: initialized profile web at /home/node/.dsh/profiles/web四阶段在隔离沙箱里跑:安装(有网)→ 列装 → 挂载 → 启动(后三步断网)。
README
dsh-perm-gate
- [English README](./README.md)
- [中文 README](./README.zh.md)
- [日本語 README](./README.ja.md)
- [한국어 README](./README.ko.md)
- [Installation guide](./INSTALL.md)
- [中文安装指南](./INSTALL.zh.md)
- [日本語インストールガイド](./INSTALL.ja.md)
- [한국어 설치 안내](./INSTALL.ko.md)
- [Changelog](./CHANGELOG.md)
- [日本語 changelog](./CHANGELOG.ja.md)
- [한국어 changelog](./CHANGELOG.ko.md)
兼容性说明: v2.0.0 自带ja/ko字典,但官方 DSH 的LocaleRuntime
只暴露zh/en(LOCALE_IDS = ["zh", "en"])。在原版 DSH 上选择ja/ko
会报locale "<id>" is not registered。请使用更新了LOCALE_IDS
(locale-settings.ts)与 LOCALES 标签(client/index.ts)的 DSH fork 并重新构建。
▼ DSH 版本适配
两个 DSH 版本线从两个长期分支分别维护,各有一套版本号系列、engines.dsh
和 npm 分发标签([发布布局](./RELEASING.md)):
| DSH 版本 | 分支 | 版本号 | npm 标签 |
| --- | --- | --- | --- |
| 0.1.0-rc.7 ~ 0.1.1-rc.x |legacy|1.x|@legacy|
| 0.1.2-alpha.1+(含 0.1.5-rc.2) |main|2.x|@latest/@dsh-0.1.2(@2.x是范围) |
版本序列号跟的是 DSH 线(1.x= DSH ≤ 0.1.1,2.x= DSH 0.1.2+),两条大版本互
相隔离:锁在^1.x的安装绝不会解析到2.x,反之亦然。engines.dsh表达同样的
分界,但 DSH 从不读取它——真正把旧 DSH 钉在 1.x 上的是版本范围与 dist-tag。
@deepseek-ai/dsh-client-runtime在0.1.2-alpha.1中已被移除——不仅仅是更名。
legacy线仍通过它访问ctx.slots;main从
@deepseek-ai/dsh-client-ui-renderer/client 获得相同的声明。两处版本敏感
接缝通过能力探测处理,而非版本号检查:(1)设置注册使用 register,两线
都存在(installSection是新增项,不是替代);(2)effectivePolicy在两
线上都是 user-approval 服务的私有方法,因此通过 typeof 探测读取,缺失
或抛错时降级为「策略未知」。
版本 2.4.1 —— 变更见 [Changelog](./CHANGELOG.md)。
一个单一自足、确定性优先、fail-closed 的 DeepSeek Harness 权限门插件。
对每个工具调用按固定优先级链裁决:
阶段 · 决策 · 含义
P0 · deny · 确定性硬拒:凭据材料 / 受保护路径改写 / 危险 shell
P1 · allow · 精确、有界的会话放行 grant
P2 · deny/allow/ask · 静态规则链:黑名单优先,其次 allow,再 ask
P3 · allow/deny/ask · 可选 LLM 语义分类器(默认关闭)
P4 · ask · 官方 approval seam
严格 fail-closed:P0 永不因 grant / 规则 / 分类器 / 人工而放行。
<!-- host-compat:begin — generated by scripts/sync-hosts.mjs from scripts/hosts.mjs; DO NOT EDIT -->
- 支持的 DSH 宿主:
0.1.0-rc.20.1.0-rc.30.1.0-rc.60.1.0-rc.70.1.0-rc.80.1.1-rc.10.1.1-rc.20.1.2-rc.10.1.5-rc.10.1.5-rc.20.1.5-rc.30.1.7-rc.10.1.7-rc.20.2.0-rc.10.2.0-rc.20.2.1-rc.10.2.1-rc.20.2.1-rc.30.2.1-rc.40.2.1-rc.50.2.2-rc.1(覆盖 0.1.0 / 0.1.1 / 0.1.2 / 0.1.5 / 0.1.7 / 0.2.0 / 0.2.1 七条线共 21 个 rc) - 运行时已验证:
0.2.0-rc.2(证据见.compat-results/)
<!-- host-compat:end -->
特性
- 命令白/黑名单 — 基于 argv 分解匹配(非裸字符串),递归下钻
sh -c/bash -c、识别管道、重定向目标、递归/强制(rm -rf)。 - deny 优先 — 命中黑名单即拒绝,胜过任何 allow。
- 凭据类型阶梯 — 七类凭据(
ssh、cloud、package、gitcreds、env、cli、db)各自可选deny/ask(默认)/readonly/readwrite四档;档位状态存于规则文档的[deny-rule:cred.<family>]行(分区 +enabled)与成对的credWriteExemptFamilies清单,设置卡一次 update 成对写回,无镜像、无半态。readwrite是唯一会退让部分 P0 的档位(仅凭据 store 的写判据,npm login 类工作流)且需卡内二次确认;根盘、受保护路径、.dsh、外发在任何档位恒拦。 - 保护分支强推开关 —
allowProtectedBranchPush(默认关)保留 P0 对保护分支git push --force/--force-with-lease/--delete的地板;开启后地板让位、落入预设git.push-force的逐次人工确认,并同步豁免黑名单三条扁平 push 词。 - 会话放行 — 精确的
(工具, 规范化 fingerprint)grant,带TTL+maxUses;换目标绝不复用。子代理继承但不可自授。 - 纯函数规则引擎 — glob/regex 编译 + ReDoS 上限、坏规则 loud fail、按源内容哈希缓存。
- 审计 — 每次决策写为
{ignorable:true}事件并带callId;模型可见理由与记录一致。 - 自动审查档位(机器值
permissive)——一个独立审批模式(区别于只读、完全权限与白名单档),既不是"自动审批",也不授予泛化权限。前端只暴露一个开关(permissive),后台四个审批策略可组合、由插件设置决定——仍对 P0 保持 fail-closed。权限下拉框与设置行都按产品名「自动审查」显示;图标见下文(内置档自带,插件档需补丁)。 - 沙箱提权自动答复(
trustEscalation)— 沙箱提权是从 shell / pwsh / edit 工具体内部(tools/pre-execute之后)发出的,所以门禁从未见过它,一个它自动放行的调用仍会弹出确认。开启后,门禁以callId精确匹配已放行调用并直接答复。
安装
需要先安装 DeepSeek Harness。
dsh plugin --profile web add dsh-perm-gate
完整的安装、升级、迁移与排查步骤见[中文安装指南](./INSTALL.zh.md)(另有
[English](./INSTALL.md) / [日本語](./INSTALL.ja.md) / [한국어](./INSTALL.ko.md))。
配置
AppContainer 沙盒(Windows;beta)
dsh-perm-gate 可以把门控放行的 shell 命令放进 Windows AppContainer 里执行,而不是裸交还
宿主。容器 token 不带任何网络能力,非回环出网被 Windows 防火墙(WFP)直接封死——不是环境
变量那种可绕过的软约束。容器 SID 由 OS 从固定名 dsh-perm-gate.ac 派生,因此
CheckNetIsolation LoopbackExempt(放行容器访问 127.0.0.1)是每台机器一次的步骤,不是每次
会话都要做出网因此只能走网络代理:
sandboxEnabled(默认false)——总开关。开启后每条自动放行的 shell 调用会被重写成启动器
调用;人工批准的调用不在沙盒范围(用户已明确知情)。启动器无法编译、或 OS 拒绝容器启动时,
该调用被拒绝(fail-closed),理由带 sandbox: … 前缀——绝不退回裸执行。
sandboxMode——workspace-write(默认:工作区 Modify + 私有 temp FullControl,系统目录靠
ALL APPLICATION PACKAGES 默认 ACE 保持可读)或 read-only。
sandboxProxy——代理参数:空(默认)跟随内置过滤代理实际绑定的127.0.0.1:<port>(需
networkEnabled);显式 URL 必须绑定回环(容器只可达回环),出网对象的过滤由该代理完成。
sandboxLoopback——exempt(默认:尝试一次性豁免,被拒时给出精确提权命令)或off。
启动器是一小段 C# 源码(assets/appcontainer-launcher.cs),首次使用时由 Windows 全系自带的
.NET Framework 编译器(csc.exe)按需编译;插件本体保持零原生依赖。真机端到端验证:
node scripts/smoke-appcontainer.mjs
已知边界:在经典 AppContainer 创建 API 已被移除的 Windows 11 25H2+ 新构建上(26200 实测),
mxc 替代尚未暴露(26600+),启动器在内核步 fail-closed;此时沙盒调用一律明确拒绝,不裸跑。
Windows 10 / 11 ≤ 24H2 走文档化的经典路径。
cordis.yml:
- id: dsh-perm-gate
name: dsh-perm-gate
config:
rulesFile: ./permissions.yaml # 可选;默认 $DSH_HOME/perm-gate/rules.yml
dshHome: $DSH_HOME
defaultAction: ask
gatePresets: [permissive, permissive-full] # 门禁生效的档位(默认值)
sessionSweep: true # 每小时清理已归档/已删除会话的门禁数据
会话清扫(session sweep)
插件启动时及每小时读取 DSH 的工作区存储($DSH_HOME/storages/workspace.json,只读),
对门禁持有授权链数据的每个会话做归类。已被 DSH 归档(global.archivedSessionIds)
或彻底不存在的会话,其决策事件会从 $DSH_HOME/perm-gate/events.jsonl 中移除,
其决策前文件快照会从 $DSH_HOME/perm-gate/snapshots/ 中删除——宿主已视为消失的数据,
审查页也不再保留其历史。活跃会话不受影响;无法归属的行(空 sessionId)永不删除;
任何失败都 fail-open:本轮跳过,一小时后重试。设 sessionSweep: false 关闭;
workspaceStoreFile 可覆盖存储路径。恢复归档会话不会找回已被清扫的历史。
规则示例:见 [examples/permissions.example.yaml](./examples/permissions.example.yaml)。
网络策略(可选开启)
本地 HTTP/CONNECT 代理,用**同一份规则文
…(truncated)
以上内容来自 npm 上的 README,我们只做格式化,不改内容。
版本
npm 上共发布:56,最后更新 2026-11-06