Repository navigation
Releases
Releases · lxwallac/dsh-vault-wall
v0.4.0 - ask mode (human-in-the-loop), post-execute verify+correct, /wall report+lint, rule history+rollback
v0.4.0 - ask mode (human-in-the-loop), post-execute verify+correct, /wall report+lint, rule history+rollback
Latest
DSH(DeepSeek Harness)插件:让 agent 看不见、碰不到你指定的敏感路径。
解决什么问题
- 你的私钥、API key、客户资料就放在本机,而 agent 为了完成任务会
glob/grep整个盘——顺手读走、写进日志、留在上下文里。 - 提示词里写「不要读 X」不可靠:模型会忘、会被绕过、会在你没看着的时候重试。
- Vault Wall 把这件事从「提示词请求」变成宿主层策略:命中规则的路径对 agent 假装不存在、或明确拒绝、或先弹窗问你。
使用场景
- 个人密钥库(
~/.ssh、D:\keys):整树隐藏,agent 连路径名都看不到(not-found)。 - 仓库里的凭据(仓库根与任意深度的
.env):一条**规则一起圈住。 - 归档 / 备份目录只读:
deny+tools限定,写入被拦、读取不受影响。 - 需要你点头才动的目录:
ask模式——弹窗写清「路径 + 规则 + 工具 + 风险等级」,同意后按 TTL 记借出,且只对被你批准的那一条路径生效。
快速示例
粘进「设置 → 保险区 Vault Wall → 以 JSON 编辑」,或在旧规则文件模式下放进规则文件:
常用命令:
/wall test D:\keys\id_ed25519 read # 试算:现在会被判成什么(不消耗借出、不改状态)
/wall report # 护栏评估:拦了多少、审批结果、有没有被绕过
/wall lint # 规则体检:过宽 / 被遮蔽 / 工具名不可达
/wall status # 规则数、熔断、借出、审计、历史
注意事项(先读这几条)
- 策略围栏,不是内核边界:shell / 代码文本按启发式匹配,防「手滑与惯性触碰」,不防恶意构造;真正的内容隐身要靠 OS 层(独立账户 / ACL / 加密容器)。
ask需要宿主提供审批通道:通道缺失、审批抛错、你按了取消,一律按拒绝处理(fail-closed),不会退化成放行。- 未识别工具(第三方 / MCP)的风险记为
unknown,比high更严——但也仍需要参数覆盖才能拦,欢迎提 issue。 - 默认开启执行后验证:一旦检出「判了拒绝却执行成功」会扣下结果、写审计并自动熔断,需要
/wall panic off才恢复。 - 结果里出现受保护路径时默认脱敏(
onLeak: 'redact');不想改内容可改成'audit'只留痕。
安装
# 从 npm
dsh plugin --profile <profile> add dsh-vault-wall
# 或从本 Release 的 tgz(国内/镜像不稳定时更稳)
dsh plugin --profile <profile> add ./dsh-vault-wall-0.4.0.tgz
装完重启 dsh,到「设置 → 保险区 Vault Wall」添加规则。
完整变更
v0.4.0 新增与修复
按《AI Agent 入门》第一章的 Harness 模型(约束 / 验证 / 纠正 + 工具风险评级 + 人在回路)
补齐护栏的后半段。v0.3 的墙只会「拦」,v0.4 会问人、事后核对、纠正循环、并且改得回来。
新增内容
- 询问模式
mode: "ask"(人在回路)
命中后不直接拒绝,而是通过官方审批通道(ctx.get('approval'))弹出确认框,把「路径 + 规则 id +
工具 + 风险等级 + 规则备注」摆给用户;只有allowed-once才放行。复核来自上下文之外的用户,
而不是问模型自己。- 三种「没通过」各有独立文案且都要求不要重试:人拒绝 / 取消 / 无可用审批通道;
- 通道缺失、通道抛错、无 agent 上下文一律 fail-closed 成明确拒绝(绝不静默放行);
- 事后兜底:
ask决策若未在审批台账里留下同意记录(门没挂上/内部异常/被绕过 pre-execute),
guard 一律按「没人问过」拒绝。 - 实现取舍:没有改走宿主的
{kind:'ask'}(dsh-tools的serviceAsk)。那条路径在用户
同意后返回allow并继续咨询单调 guard,而 guard 对同一条 ask 规则仍会判ask,
等于用户刚点的「允许」被自己的墙否掉;因此审批在 pre-execute 门里自己做,并在 guard 之前把
同意写进按 exec 记账的审批台账。
minRisk/remember/borrowTtlMs(仅 ask 规则)
风险门槛(低于门槛的工具调用直接放行,不打扰人)、同意后记一条 TTL 借出(默认 10 分钟)、
借出时长(0= 一次一授权)。借出只覆盖被批准的那一条路径——同意读一个文件不等于同意整棵树;
要目录级授权用/wall borrow add <目录>(弹窗文案里明确告知)。写在非 ask 规则上会 fail-loud。- 工具风险评级
src/risk.js:low(只读)/medium(写入)/high(任意执行、不可逆),
未识别工具 =unknown,秩高于high(第三方/MCP 默认从严,故障安全默认值)。 - 执行后验证
src/verify.js(tools/post-execute)- 授权一致性校验(结构化,可信):比对 guard/审批门当时真正做出的决策与执行结果——
判了拒绝却执行成功即verify-bypass,扣下结果、记审计;autoPanicOnBypass(默认开)顺手熔断。
这条正好补上 v0.3 唯一的 fail-open 缺口(guard 内部异常时放行); - 泄漏扫描(文本启发式,尽力而为):结果里出现受保护根时按
onLeak处理——redact(默认,
整条路径一起脱敏,不漏文件名)/audit/block。已授权的路径不算泄漏。
- 授权一致性校验(结构化,可信):比对 guard/审批门当时真正做出的决策与执行结果——
- 循环纠正
src/correct.js:同一 agent × 同一规则 × 同一路径的重复触墙计数(默认 3 次,
5 分钟窗口)触发纠正——guard 的拒绝文案追加「这是策略决定、不是临时故障、别再重试、去告诉用户」,
tools/post-execute把该次结果整条换成纠正文案(可选repeatDenialAction: 'panic'直接熔断)。
收到新的用户消息即清零(与官方 repeat-tool-reminder 同一取舍)。 - 护栏评估
/wall report:一页给出拦截/放行与占比、判决分布、审批结果、bypass 与泄漏、
重复触墙排行、从未命中的规则、规则修订、生效配置,并给出建议动作。 - 规则体检
/wall lint:过宽(覆盖主目录)、被前一条同模式规则遮蔽、路径不存在、重复路径、
中段**的已知边界、tools里写了引擎看不见形状的工具名、deny会暴露墙的存在、
ask 的通道/门槛/remember——逐条结论(warn/info)与建议。 - 可回滚的规则修订
/wall history/snapshot/rollback
每次成功应用规则都记一条修订(内容相同去重,只增不改),historyFile可落盘跨重启保留;
回滚会写回规则源(settings 命名空间或规则文件)并在写不回去时明确说「只改了内存,重启会回到
旧规则」,回滚本身也记为新修订。 /wall test/status/decisions增补:试算打印风险等级与 ask 行为预告;状态页显示版本、
指标、循环计数、行为开关、历史;决策列表带risk=。- 设置页 UI(
browser/client.js):新增「询问」模式药丸与 ask 专属表单行(最低风险 / 记住 /
借出时长),校验与宿主引擎口径对齐(非 ask 规则带上 ask 字段会被页面拦下);工具清单补齐
str_replace_editor/run_code/cordis_define。 npm run test:local:node --test会为每个测试文件 fork 子进程,在受限环境(文件沙箱、
部分容器/CI)会被spawn EPERM拒绝;这个脚本用node:test的编程式run()在同一进程内
顺序执行同一份清单,作为等价通道。- 测试从 81 个增加到 204 个:新增
tests/risk|ask|verify|correct|metrics|history|report.test.js,
并扩充rules/borrow/wall-core/console/client-bundle/index-wiring
(含「VERSION 必须等于 package.json version」这条发版栅栏)。客户端测试新增探针渲染:
直接渲染规则编辑弹窗,断言 ask 行出现、保存时只写 ask 字段。
修复的 Bug
- 脱敏只换掉了根路径,文件名仍然泄漏:规则
D:\keys命中结果里的D:\keys\id_ed25519时,
旧实现只替换D:\keys,留下\id_ed25519。现在整条路径 token 一起脱敏。 - 已授权路径被自己判成泄漏:同意读取
D:\keys\id_rsa后,结果里出现该路径会被泄漏扫描命中并被
脱敏(等于把刚批准的内容抹掉)。授权判定现在两个方向都算授权。 - 无 settings 服务时墙有 60 秒的「无规则」窗口:
apply()早先把旧规则文件的回退放在 watchdog
的 60s 截止处,期间engine === null而 guard 对所有路径放行。现在 settings 服务缺席时当轮即用
旧规则文件兜底。 - 审计丢失
risk字段:AuditRing.push只保留白名单字段,/wall decisions读到的risk
永远为空。现在risk与approval一并落审计。 isWindowsHost()与注释不符:注释说「拿不到 UA 就按 Windows 判」,实现却会返回false,
导致无navigator的环境把C:\...判成非法路径。
兼容性
version: 1规则文档格式向后兼容:v0.3 的hidden/deny规则照常工作,ask与三个新字段
是可选项;v0.3 写的规则文件、settings 文档无需迁移。- 行为变化(有意为之):未识别工具的风险按
unknown(高于high)计入 ask 门槛与报告;
新增的tools/pre-execute、tools/post-execute、agent/pre-step三个监听器在默认配置下即生效。
不需要验证/纠正时可关:onLeak: 'audit'、autoPanicOnBypass: false、
repeatDenialThreshold: 0、askEnabled: false。
v0.3.0
v0.2.31
v0.2.30
合规发布 0.2.30:
- 修复保险区空白(rawState 声明恢复 + uiSvc 只走 ctx.get,0.2.28/0.2.29 已验)
- bundle patch 移除机器绝对路径(C:/Users/dell/...),路径改走默认解析链 config > env DSH_VAULT_WALL_RULES > ~/.dsh/vault-wall-rules.json;需要自定义路径时在 profile 的 cordis.patch.yml 覆盖该行 config
- 对齐官方规范审计:函数插件导出形态、客户端 bundle 协议、manifest dsh.bundle/dsh.client、测试 41/41 通过
{ "version": 1, "rules": [ { "id": "keys", "mode": "hidden", "paths": ["D:\\keys", "C:\\Users\\you\\.ssh"] }, { "id": "repo-env", "mode": "hidden", "paths": ["C:\\work\\repo\\**\\.env"] }, { "id": "archive-ro", "mode": "deny", "paths": ["D:\\archive\\**"], "tools": ["write", "edit", "str_replace_editor", "bash", "pwsh"] }, { "id": "wallet-ask", "mode": "ask", "paths": ["C:\\Users\\you\\wallet"], "minRisk": "medium", "remember": true, "borrowTtlMs": 600000 } ] }