- Accueil
- Plugins
- Sécurité et permissions
- dsh-approval-gate
dsh-approval-gate
iamnewhands/dsh-approval-gate
Fork maintenu de dsh-approval-gate. Si une opération neutre atteint le seuil de confirmations et que le juge est indisponible, elle est approuvée automatiquement au lieu de redemander à un humain. Les explications aux approbateurs sont générées en chinois à partir du mode sandbox, de la commande et des chemins réels. Inclut aussi refus déterministe d’exfiltration d’identifiants et de destruction de chemins système, masquage de l’entrée du juge, chaîne de modèles candidats, règles d’autorisation par fingerprint et vue avec diff unifié et annulation en un clic.
Installer
dsh plugin --profile web add github:iamnewhands/dsh-approval-gateREADME
简体中文 | English
dsh-approval-gate
DeepSeek Harness 自动审批门控 —— 最小人工介入,安全自动放行、危险转人工(fail-safe)。
判定模型预判每次沙箱越界:常规操作自动放行,硬风险操作(删除 / 凭据 / 远程 / 系统 / 批量)永远转人工确认;学习沉淀只针对你确认过的操作,并提供界面化人工审查入口。
判定管道:硬拒(凭据 / 系统路径,判定模型无权推翻)→ 硬事实人工 → 危险词 → 危险动作围栏(v0.9.7)→ 敏感路径永远人工(v0.9.8)→ DSH 配置自动放行 → 白名单(v0.9.8 按命令锚定)→ 定域放行(v0.9.7)→ 工作区外一律人工(v0.9.8)→ denyRules → 脱敏 → 判定(JSON 硬类别优先 → allow/ask/deny)→ 学习沉淀。
来源:本项目是 moon09300731/dsh-approval-gate 的 fork, 在其基础上修复了若干缺陷并扩展了多机规则共享。原作者版权与 MIT 许可见 LICENSE。 本仓库(IamNewHands/dsh-approval-gate)为维护中的版本。 其中 5 项能力移植自 NanmiCoder/dsh-auto-mode(MIT),见下文「吸收自 dsh-auto-mode」。
✨ 特性
- 💾 全量导出 / 导入(v0.9.13):设置页「备份与迁移」卡片把本机的规则与判定参数整份导出成一个 JSON(白名单 / 永久人工 / 危险词 / 硬类别 / 阈值与超时 / 定域与区外开关 / 裁判模型 / 学习进度),拷到另一台机器导入即可同步开始使用。导入可选合并(并集,本机规则保留,幂等)或覆盖(按设置包替换);「判定参数与裁判模型」可单独关掉;「会话规则提升为全局」专治跨机器会话 id 对不上、会话规则永不生效。导入前自动备份(
import-backup-*.json,可整份回滚),被拒绝的导入不写盘。导出包只认白名单字段、不含机器路径,也不碰 profile 的cordis.patch.yml(权限预设仍走「一键配置」) - ⚡ 模型风险预判:每次沙箱越界由判定模型给出严格 JSON 裁决(
allow/ask/deny),可回补操作自动放行 - 🎛️ 裁判模型可选(v0.9.2):设置页「裁判模型 · 与主力模型解耦」卡片直接下拉选择判定模型(路由 + 模型,首项「跟随 agent 默认模型」),不用手改
allowlist.json;模型目录不可用时降级为手填输入框。判定模型选错是「每次审批都转人工」的常见真因(多步工具循环型模型在判定超时内跑不完) - 🛑 确定性硬拒(吸收):凭据外泄与根/系统路径销毁基于真实路径与凭据事实直接拒绝(不弹窗),判定模型无权推翻;home 根与 DSH 配置档的例外仍转人工
- 🗂️ DSH 配置自动放行(v0.9.5):
$DSH_HOME下的 profile / 插件 / 依赖改动(cordis.patch.yml、package.json、pnpm-workspace.yaml、skills/、node_modules/…)不再弹人工——实测最近 7 天 36 次人工里有 20 次是这类。两道例外仍转人工:审批门自身的数据目录$DSH_HOME/auto-approve/(改它等于放行自己)与凭据类文件名(api-key/token/secret/credential/.env/id_rsa/*.pem/*.key)。本档排在危险词之后,命中不可逆危险词仍先转人工。(v0.9.1 那条「DSH_HOME 写入永远人工」已被本版反转,理由与残余风险见 CHANGELOG) - 🎯 按命令锚定 + 工作区外一律人工 + 敏感路径永远人工(v0.9.8):规则的
contains/keywords改为只按真实事实(命令 + 真实目标)匹配 —— 说明措辞不再授予权限(实测 30 天 897 条自动放行里 30 条命令里根本没有规则词,例如gh run view被contains:"github"放行)。指纹来源同步锚定(追认 / 沉淀 / 学习都取自命令),追认的contains改为目录级,同一目录换个文件名不用重新审批。工作区外一律人工(outside/mixed→ 人工,unknown不拦),排在白名单之后,所以你手写的区外规则(%APPDATA%\Rime等)仍然生效;$DSH_HOME的命令类维护(pnpm --dir … install、改 pin)由 DSH 配置档补口继续自动放行(实测保住 54 条)。敏感路径形态永远人工:.ssh/.aws/id_rsa/credentials*/.env*/*.pem/*.key/.git-credentials/Cookies/Login Data/ 审批门自身数据目录 —— 工作区内的.env同样命中,而src/credential/transport.ts这类源码文件不误报。实测:人工提示 147 → 178 次/30 天(+21%),换来 30 条真误放行被修掉 + 2 条凭据路径永远人工。两个开关(定域放行 / 工作区外一律人工)都可一键回退 - 🚧 危险动作围栏 + 定域放行(v0.9.7):工作区内的操作按定域直接放行(事件记
verdict: scope,判定器零调用),同时在工作区内也拦下六类动作并转人工:网络下载(curl/wget/iwr/Invoke-RestMethod/gh release download…,URL 全为本机时豁免)、动态执行(iex/-EncodedCommand/FromBase64String/| bash…)、依赖安装(pnpm/npm/pip install/docker pull…,指向$DSH_HOME时豁免)、持久化(schtasks/reg add/New-Service/Set-ExecutionPolicy…)、递归删除(Remove-Item -Recurse/rm -rf/git clean…;单文件清理不拦)、可执行产物(写.exe/.dll/.ps1/.bat/.git/hooks//.github/workflows/…)。围栏排在白名单与学习之前——已沉淀的contains宽规则盖不过它,否则一次追认就能把「下载」永久放行。拦截原因进事件与卡片(字段表格新增「拦截原因」行)。实测 30 天:围栏命中 23 次(其中 13 次原本自动放行),定域放行省下 23 次人工提示,净少 10 次。设置页可一键关闭定域放行。诚实交代:围栏是文本特征匹配,能被刻意混淆绕过,它挡的是「模型被诱导」,不是定向攻击 - 🧭 目标定域(v0.9.6):审批记录新增「目标位置」行(
工作区内/工作区外/跨工作区内外/无法定域),与「影响范围」(沙箱模式)分开成两行。命令类工具的绝对路径不再丢失(实测 628 条带命令的真实事件里 458 条原本提不出任何绝对路径),说明措辞里的相对片段(origin/main、IamNewHands/repo、.git/objects)不再冒充目标;引号内含空格的路径完整保留,/d/...(Git-Bash 写法)折算到D:;系统程序位置(bash.exe)与/dev/null不算数据目标。只读目标只进targets,不进files—— 否则Get-Content ~/.ssh/id_rsa会把私钥复制进审批门自己的快照目录。..穿越与「一个绝对路径都没有」一律记为无法定域(fail-closed)。判定模型同时拿到这些真实路径,不再只凭措辞猜。本版不改动确定性裁决逻辑(硬拒 / 危险词 / 白名单 / 学习一行未动),但判定模型的输入变了,因此判定层对命令类调用的裁决可能与以前不同 - 🔬 危险词按边界匹配(v0.9.1):关键词命中要求词/标志边界,
git push --force-with-lease(带租约的安全强制推送)与docker rmi不再被当成push --force/docker rm;真正的push --force仍照旧转人工 - 🔐 审批作用域可选(v0.9.4):追认时可指定仅本次 / 本会话 / 全局(默认本会话;「仅本次」不写规则,只放行重试的那一次);设置页的「新审批沉淀的作用域」决定人工确认后自动沉淀写在哪个范围。学习计数按
会话|工具|模式|类别隔离,任一会话都无法靠反复触发养出影响其他会话的规则。你手写的规则、仓库种子、内置默认规则,以及本次升级前沉淀的旧规则都是全局生效;会话规则可在白名单卡片一键「提升为全局」。denyRules(你拒绝过的操作)有意保持全局:拒绝侧跨会话只会多弹一次人工,不会放行任何东西 - 🧱 来源校验补 scheme 与端口(v0.9.3):来源必须与请求自身的 Host 逐字同源(scheme + host + port),
javascript:/data:/null来源一律拒绝;只有「请求 Host 是回环地址且来源是回环别名」才允许跨端口(127.0.0.1 / localhost / [::1])。DNS rebinding 的字面同源页面靠凭据围栏拦截(见 GUIDE) - 🔒 判定输入脱敏(吸收):密钥与大块正文在送判定模型前被抹除/截断,避免密钥随判定请求出站
- 🛡️ 硬风险永远人工:删除、凭据、远程/生产、系统路径、批量不可回补五类操作直接转人工,不计数、不学习、不可追认;这是一道对称安全闸——无论判定模型给
allow还是deny,命中硬类别一律转人工(v0.7.0 修正:此前deny会抢先静默拒绝,使硬类别配置失效) - 🎯 确认制学习:同一会话内,同一操作人工确认 N 次后,第 N+1 次起自动放行;沉淀规则携带操作指纹,只放行你确认过的操作,作用域按设置页的「新审批沉淀的作用域」写(本会话 / 全局)
- 🧠 语义同类验证:措辞变化但意图相同的操作,由判定模型对照你的确认样本语义判断,不再依赖关键词
- ♻️ 判定器失败兜底(吸收,v0.8.0 语义修正):判定器不可用第一次就转人工(不再静默拒绝——判定器挂了不等于你的操作有害);失败原因(超时/上游报错/正文为空)写进审计与审批记录;批准后沉淀带指纹的放行规则,同类调用不再过判定器。阈值
judgeFailureLimit(默认 1,设为 >1 回到旧的"先静默拒绝"节奏) - 🔗 判定模型候选链(v0.8.0):主判定模型 → 会话默认模型 → 内置兜底;单通道抖动(502/超时)不再等于判定器整体不可用
- 🧮 学习兑现优先于判定器(v0.8.2):确认计数已满阈值(
riskyThreshold)的neutral操作,在判定器不可用时直接按已完成的确认放行,不再因为判定器抖动而反复弹人工审批。硬拒 / 硬事实 / 危险词 / 白名单仍排在判定之前,硬风险类别照旧每次人工确认 - 🧾 提权提示永远写清命令与目标(v0.8.3):提权说明固定包含「命令 / 目标路径」两行,host 没给就写明
host未提供;danger-full-access追加「不限定路径,本次授权覆盖整机」,避免被误读成单路径授权。命令按callId严格命中失败时回溯最近同名调用并标注来源(仅影响给人看的说明,不参与硬拒/规则/快照判定) - 🩺 会话事件读取根因修复(v0.8.4):此前一律读
session.events,而 DSH 的Session只有snapshotEvents()/ownEvents()—— 结构化参数、确定性硬拒层、判定模型的用户授权来源三处因此长期失效。现按snapshotEvents() → ownEvents() → events依次取事件。行为变化:写入C:\Windows\...、~/.ssh等受保护位置的调用会直接硬拒且不弹窗;危险词层能看到真实命令,命中危险词的操作更常转人工 - 🧹 没有命令的工具不再写命令行(v0.8.5):只有命令类工具(
pwsh/bash/terminal-bash等)才输出「命令」行,write/edit只显示目标路径,文件类审批不会再挂一句毫无信息量的命令:host未提供 - 📊 审批说明改成字段表格(v0.9.0):审批记录行内渲染操作类型 / 操作路径 / 影响范围 / 执行命令 / 模型说明五个字段——操作类型做命令级判定(
Remove-Item/rm/format/git reset --hard→ 删除,git … push/gh release/npm publish/scp→ 推送发布,write→ 新增写入,edit→ 修改),影响范围按沙箱模式给后果(整机 / 工作区 / 只读);删除红、新增绿、修改蓝、推送发布琥珀。宿主审批卡的纯文本也改为字段分行(操作:… / 路径:… / 影响:… / 命令:… / 原因:…),不再是一整段散文;顶部提示条用一行摘要。事件新增facts字段承载结构化事实(老事件由事件 API 按已记录事实现算补上,不回写文件),缺facts时照旧回退文本渲染 - 🔢 「审批」tab 显示条数(v0.9.0):顶部 tab 文案变成
审批 (12),数字是本会话「审批」视图真正列出的记录数(等待人工的记录只活在提示条里,不计入),不打开 tab 也能一眼看出有没有新记录 - 💬 提示层减负(吸收):预设激活期间向会话注入
<auto_approve_policy>,从源头减少需要判定的越界请求 - 🔧 配置热更新:
allowlist.json修改即时生效,无需重启 - ✅ 人工审查 UI:自动放行时输入框上方出现绿色提示;「审批」视图(轨迹右侧)展示当前会话完整放行时间线,静默拒绝单独标红
- 🈶 审批说明中文化(v0.8.1):审批卡片与「审批」视图的说明一律中文——原文是英文或带宿主英文前缀(
escalate sandbox to …)时,用真实事实(目标沙箱模式、真实命令、真实目标路径)生成中文说明并交代后果(可写范围 / 能否回滚 / 是否影响工作区外);命令与路径原样保留,模型原文作附注追加。事件新增zh字段承载中文说明,justification原文仍留档 - 🔔 拒绝提示条常驻(v0.7.0+):静默拒绝与人工拒绝的提示条不再几秒消失,而是一直挂在对话框上方(带「查看审批记录」/「重新审批通过」按钮),直到你切到「审批」tab 才收起;已读位置本地持久化,刷新不丢也不重复打扰。追认过的拒绝已放行,既不计入待处理,也不会再弹红色提示条(v0.7.1)
- ↩️ 追认被拒操作(v0.7.0+):审批记录里的静默拒绝可一键「重新审批通过」——写入带操作指纹的自动放行规则并投递重试指令让 AI 重跑。围栏:确定性硬拒档与硬风险类别不可追认(给按钮就是假承诺)
- 📄 文件改动对比与撤销(v0.5.0+):审批涉及的文件可点击查看 unified diff——变动行带上下 5 行上下文、多处修改按 hunk 分区并以「N unmodified lines」分隔条折叠、绿加红删灰上下文、双行号;一键「撤销此改动」投递指令让 AI 按快照恢复文件
- 🗂️ 会话级快照管理(v0.5.0+):快照按事件归属会话,审批视图按当前会话统计;清理支持「仅清本会话」与「清空全部」两档,避免误删其他会话未查看的 diff 记录
🔌 吸收自 dsh-auto-mode
以下 5 项移植自 NanmiCoder/dsh-auto-mode(MIT License),按本仓库的判定管道语义改写并补充了回归测试:
| 能力 | 说明 |
|---|---|
| 确定性硬拒 | src/paths.mjs + hardDenyFacts():路径事实熔断(文件系统根 / 系统与凭据关键路径 / Windows 设备命名空间 / 保留设备名)+ 凭据外泄判定,分「直接拒绝」与「转人工」两档 |
| 判定输入脱敏 | src/sanitize.mjs:私钥/令牌/Bearer/key=value → [redacted-secret];密钥类字段整字段抹除;大块正文只留长度;深度 3 / 数组 25 / 对象 50 |
| 结构化裁决协议 | src/classifier.mjs:严格 JSON {decision, reason, category},替代原文本 SAFE / RISKY:<类别>;任何格式偏差抛错并 fail-safe |
| 连续失败计数 | 按会话计数;judgeFailureLimit 默认 1(第一次失败即转人工,v0.8.0 修正),设为 >1 则前 N-1 次静默拒绝、第 N 次转人工;成功即清零。失败原因(超时/上游报错/正文为空)记入审计与事件 |
| 动态系统提示 | systemPrompt.context 注入 <auto_approve_policy>,仅在本预设激活时输出 |
差异:上游挂在工具管道(ctx.tools.guard + tools/pre-execute)且只做一次性判定、无跨会话学习;本仓库挂在 approval/request,保留确认制学习、操作指纹、同类语义验证与快照撤销。
📸 界面速览
① 审批视图

「审批」标签页(轨迹右侧)按时间倒序展示当前会话的自动放行与人工审批记录:每条记录含工具名(bash / edit)、判定标签(「自动放行 · Flash 判定安全」「人工通过」等)、时间与操作说明。顶部统计栏显示本会话的 diff 快照占用(2.9 KB · 3 条),并提供两个清理入口:「仅清本会话」(只删除当前会话的快照,不影响其他会话未查看的 diff)与 「清空全部」(二次确认后清空所有会话,防止误删)。
被静默拒绝的记录(红「已直接拒绝」)额外带一个 「重新审批通过」 按钮:点了就写入带操作指纹的自动放行规则,并向会话投递重试指令让 AI 重跑该操作。标题旁的 待处理 N 角标显示还有几条拒绝没追认。追认之后该行翻转为 「已追认放行 · …(曾直接拒绝)」 完成色,并从待处理计数中移除。确定性硬拒档(凭据外泄 / 系统路径销毁)与硬风险类别(删除 / 凭据 / 远程 / 系统 / 批量)不显示该按钮——前者白名单盖不过、后者必须每次人工确认,给按钮就是假承诺。
② 文件改动对比(diff)

点击审批记录中的文件即可打开对比面板:以 unified diff 展示改动前后差异——新增行绿底(+)、删除行红底(-)、上下文行灰底;左侧显示原/新双行号;多处修改按 hunk 分区,块间以灰色「6 unmodified lines」分隔条折叠未变更区间。顶部统计 +2 / -2 行变更 · 20 行未变。底部 「撤销此改动」 一键向对话投递撤销指令,AI 将按审批前的快照恢复文件。
③ 设置 · 自动审批

设置页「自动审批」分区提供完整配置:初始化权限预设(一键写入 cordis.patch.yml 的 auto-approve 预设)、备份与迁移(全量导出 / 导入,v0.9.13)、当前判定管道总览(DENY → 白名单 → denyRules → Flash → 学习)、危险词黑名单(预置条目 + 自定义添加)、以及热更新说明(修改即时生效,无需重启)。
🚀 快速开始
dsh plugin --profile web add "github:IamNewHands/dsh-approval-gate#main"
npm 上的
dsh-approval-gate是上游 0.5.0,不含本仓库修复,请勿按包名安装。
- 配置权限预设:在
~/.dsh/profiles/web/cordis.patch.yml添加auto-approve预设(详见指南) - 重启
dsh web - 选择预设:会话权限下拉选中「自动审批(Flash)」
📖 文档
📄 License
MIT
Plugins associés
dsh-purge
hunyisage/dsh-purge
dsh-infinite-gen-4
minglink/dsh-infinite-gen-4
dsh-purge
mmparko/dsh-purge
cc-safety-net
kenryu42/cc-safety-net