- Inicio
- Plugins
- Seguridad y permisos
- dsh-warden
dsh-warden
dingchenhui0618-arch/dsh-warden
Adversarial review gate for tool calls. It hooks `tools/pre-execute`: a local regex pass over destructive commands (`rm -rf`, `git push --force`, `git reset --hard`, `DROP TABLE`, `format`, disk writes) and sensitive paths (`.env`, `id_rsa`, `.ssh`, `.git/`, `$DSH_HOME`) runs first with no latency, and only a hit is escalated to one review-model call that returns allow or deny. Plain reads and ordinary writes never enter that path, so everyday work pays no added delay. Every verdict is shown live in the Web GUI.
Instalar
dsh plugin --profile web add github:dingchenhui0618-arch/dsh-wardenREADME
dsh-warden
给 DeepSeek Harness 的对抗式审查门:危险的工具调用在执行前由一个独立的小模型复核,并在 Web GUI 里实时显示每一次判定。
为什么要有它
DSH 自带的工具审批只有一种粒度——弹窗问人。要么每次都问(打断心流),要么整个关掉(危险操作彻底没人把关)。warden 给第三种:平时零打扰,只在真正危险的那一类调用上花一次便宜的模型调用。
它挂在 DSH 留给插件的唯一前置钩子上:
tools/pre-execute -> { kind: 'allow' } | { kind: 'deny', reason } | { kind: 'ask' }
它拦什么
两层,第二层只对第一层的命中者触发:
第一层(零延迟,本地正则)
- 破坏性命令:
rm -rf(任意旗标顺序)、Remove-Item -Recurse、rmdir /s、format、mkfs、dd if=、DROP TABLE/DROP DATABASE、git push --force、git reset --hard、git clean -f、shutdown、Clear-Disk… - 敏感路径写入:
.env、credential、id_rsa、.ssh、.git/、settings.*、cordis*.yml、AGENTS.md、$DSH_HOME下任何文件
第二层(一次模型调用) 把「工具名 + 风险类别 + 完整参数 + 当前会话目标」交给审查模型,按自然语言规则判该不该拦。
普通读写(read/grep/glob)完全不进这套逻辑;普通命令和普通文件写入只计数、不送审。日常工作的额外延迟是 0。
安装
已发布到 npm,装到的是预构建版本(lib/ 是入库的构建产物,不是装的时候现编),不需要授权任何构建脚本:
dsh plugin --profile <你的 profile> add dsh-warden
也可以直接从 GitHub 装:
dsh plugin --profile <你的 profile> add github:dingchenhui0618-arch/dsh-warden
装好后重启 DSH,对话视图里出现「审查」Tab。(桌面端在应用里安装插件,profile 由应用自己管理,不用手敲上面的命令。)
规则
内置一份默认规则(默认放行,只拦不可逆破坏与明显跑偏)。要改就写 $DSH_HOME/adversary.md——文件存在时完全覆盖内置规则,且按 mtime 自动重载,改完点面板上的「重载规则」即可,不用重启。
面板
对话视图 →「审查」Tab:
- 计数:工具调用 / 有风险类别 / 送审 / 放行 / 拦截 / 异常降级
- 最近 60 条判定:时间、工具名、风险类别、耗时、实际使用的模型、拦截理由
- 当前规则来自内置还是文件、文件路径、规则预览

审计
每一次送审的调用追加一行 JSON 到 $DSH_HOME/warden-audit.jsonl(时间、工具、类别、决定、理由、模型、耗时)。未送审的普通调用只进内存环形缓冲,不落盘——否则审计会被普通命令淹掉。
运行时卸载
dsh 0.1.6 起,插件依赖在运行时解析,并且支持在会话中途卸载插件。所以这个插件的每一处注册都有对应的拆除:
tools/pre-execute监听器随 fiber 回收/dsh-warden路由与注入的<style>各自持有 disposer- client 的共享轮询计时器有一条独立的清理路径——它活在模块作用域,卸载时不能只指望 React 卸载
面板是可丢弃的那一半:如果路由注册失败(webServer 契约变动、宿主没有 web server),插件会吞掉这个失败继续跑。闸门必须活着,面板没有就没有。
test/host.test.mjs 里有一组测试专门钉这件事:跑完全部 disposer 之后路由和监听器都必须消失;webServer.register 抛异常时闸门仍要能拦截;一次跨过卸载点的审查既不能抛异常也不能把自己重新注册回去。
它不做什么(重要)
- 不阻塞正常工作。 任何异常路径一律放行:模型不可用、上游报错、流被取消、输出无法解析、参数无法序列化、目标查询抛异常……全部
allow。这个插件最坏的表现是「什么都不做」。 - 永远不返回
ask。 审批弹窗关闭时ask会退化成拒绝,一个犹豫不决的审查员会静默掐死用户的正常工作。 - 分类基于工具名 + 参数模式,不是工具自报的类型。这是刻意的:插件作用域里读不到 agent 作用域的工具注册表。未知工具靠参数里的破坏性特征兜底。
- 不是安全边界。 它降低误操作概率,不防恶意代码——同一进程内的插件本来就能绕过它。
开发
node scripts/build.mjs # 零依赖构建(不需要打包器),产出 lib/
node --test # 30 个测试
测试分两组:classify 是纯函数覆盖;host 用 stub ctx 驱动真实的 apply(),把四个结局都钉住——拦截、放行、五种失败降级、以及「惰性调用一次模型都不调」。
lib/ 是构建产物,改 src/ 后必须重新 build。
License
MIT
Plugins relacionados
dsh-infinite-gen-4
minglink/dsh-infinite-gen-4
cc-safety-net
kenryu42/cc-safety-net
api-relay-audit
toby-bridges/api-relay-audit
dsh-redteam-model
seaof0/dsh-redteam-model