- Home
- Plugin
- Sicurezza e permessi
- dsh-approval-gate
dsh-approval-gate
iamnewhands/dsh-approval-gate
Fork mantenuto di dsh-approval-gate. Se un’operazione neutra raggiunge la soglia di conferme e il judge non è disponibile, viene approvata automaticamente senza richiedere di nuovo l’intervento umano. Le spiegazioni per chi approva sono generate in cinese dal modo sandbox, comando e percorsi reali. Include inoltre diniego deterministico di esfiltrazione credenziali e distruzione di percorsi di sistema, mascheramento dell’input del judge, catena di modelli judge, regole per fingerprint e vista con diff unificato e ripristino in un clic.
Installazione
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