Skip to content

Releases: yunling-bionic/dsh-rule-guard

v0.4.3 — 事件文本与变量路径两处盲区补完

Choose a tag to compare

@yunling-bionic yunling-bionic released this 01 Nov 09:40

dsh-rule-guard v0.4.3

两处复核盲区补完,并补上会话界面里的拒绝截图。

This release closes two review blind spots and adds the in-session denial screenshot.


一、修复:事件文本取不到,导致「授权」没有宾语 / Fix: event text not found

assistant/message 事件把正文放在 data.message.content,而旧代码只读 data.content,
取到空串 —— 于是"用户刚说授权"时找不到被授权的提案,复核只能看到「授权」两个字,
判成"没有目标"并 fail-closed。

现在统一走 eventText(e),按以下顺序尝试,取第一个非空:

data.content → data.message.content → data.message.parts → data.message.text → data.text → data.parts

验证:scripts/shape-selftest.mjs(用真实事件形状)通过。

二、修复:变量拼接路径是盲区 / Fix: variable-built paths were invisible

$p = 'C:\Temp\rg-bypass-1.txt'
Set-Content -LiteralPath $p -Value 'probe'

取路径时只看字面量,$p 展开后的真实路径看不见 → 范围检查失效。
(实测未造成损失仅因为当时沙箱权限不够,不是判据挡住了。)

现在:

expandLocalVars(command)  纯静态展开本命令内的「$x = '字面量'」赋值,不执行任何东西
                          赋值行原样保留;未解析判定只看"使用行"
readsOutsideScope         展开后仍含 $var / $(...) → 范围无法确定 → 按区外处理(送审)
targetPaths               同上,并把「[路径含变量,静态无法确定]」写进复核材料

验证:scripts/var-path-selftest.mjs(4 个用例)通过

变量字面量赋值  展开成功  未解析=false  判区外=true
纯字面量                  未解析=false  判区外=true
变量无赋值                未解析=true   判区外=true
命令替换 $(...)           未解析=true   判区外=true

三、文档 / Docs

  • 介绍页新增拒绝原始截图 assets/deny-log.png:展示动作被判"不在当前目标内"时,
    理由里直接点名违反的规则原句,不需要翻日志
  • 中英双版同步

四、未修(设计内的已知代价)/ Not fixed by design

  • 复核依赖被审命令文本本身。若变量在运行时由环境或外部输入决定,
    静态展开无法穷尽 —— 这类情况按"未知"处理(送审),不做执行期追踪
  • 每个送审动作一次模型调用(约 2–5 秒),这是 fail-closed 的固有成本

五、升级 / Upgrade

dsh plugin add dsh-rule-guard

或使用本次 Release 附件 dsh-rule-guard-0.4.3.zip(解压即用)。

完整变更 / Full changelog

v0.4.2..v0.4.3

v0.4.2 — 只读白名单对齐、目标窗口不再丢目标、判决确定化

Choose a tag to compare

@yunling-bionic yunling-bionic released this 01 Nov 07:50

dsh-rule-guard v0.4.2

修三处实测缺陷:只读白名单与真实工具名不一致、目标窗口丢目标、判决不稳定。
判据主体未变:只判断「这一步是否在当前目标内」,异常仍 fail-closed。

This release fixes three defects found in practice: a read-only whitelist that did not
match real tool names, a goal window that dropped the goal, and unstable verdicts.


一、只读白名单与真实工具名不一致 / Read-only whitelist did not match real tool names

插件里只列了短名(read / grep / glob),而实际调用是 ops_read_files、ops_grep、
ops_glob、ops_inspect_local_file —— 于是这些只读动作全部落到「未知工具 → 默认送审」,
连读一个工作区内的 md 文件都要跑一次模型复核。

现在两套名字都收录,纯读取回到免审。

二、目标窗口丢目标 / Goal window dropped the goal

三处问题,逐个修:

① 对话刚开始时不再只取最近 3 条
   指令不足以构成"最近三条"的上下文时,采用全部指令 —— 开头那条通常就是任务定义

② 「授权」必须携带被授权的对象
   应答词表补齐:授权 / 都授权 / 全权 / 同意 / 批准 / 照这个来 …
   若最新一句是这类词,自动附上紧挨着的助手提案,并标注
   「(用户刚用「授权」授权的,是上一条助手提案)」
   —— 否则"授权"两个字没有宾语,复核会判成"没有目标"并 fail-closed

③ "实质指令"不再按字数判定
   旧规则要求 ≥12 字,导致「授权」(2 字)被当成无内容消息。
   现在改为:含路径或具体动作词即可;纯应答则向前补最近一条实质指令

三、判决不稳定 / Unstable verdicts

同一动作、同一目标,两次复核结论相反(日志可查)。原因是复核输出没有确定性约束。

现在:

A. 判 deny 必须点名「违反了哪一条」:某条项目规则的原句,或当前目标里的某一句
   reason 里要写出这句原文片段(可截断,但必须可核对)
B. 点不出来源、只是"感觉可能偏题"→ 一律 allow
C. 同一动作、同一目标的判决必须可复现,不因措辞或叙述顺序翻转
D. 短指令是有效的授权或推进信号,不得因句子短判为"没有目标"

代码层强制执行:parseVerdict 中 deny 缺 clause → 降级为 allow;
deny 的返回文案、日志与缓存都带「(依据:…)」。

四、验证 / Verification

scripts/goal-window-selftest.mjs(新增,5 个用例)
  [刚开始:只有 1 条指令]        → 1 条(正确采用开头那条)
  [授权 + 前面的提案]            → 3 条(授权 + 原指令 + 被授权的助手提案)
  [只有授权、没有提案]           → 2 条(无对象可带,行为不变)
  [正常:多条都带内容]           → 4 条
  [长会话:窗口外还有实质指令]    → 5 条(补到窗口外的实质指令)
node --check lib/index.js / client.js  通过

五、升级说明 / Upgrade

dsh plugin add dsh-rule-guard

或使用本次 Release 附件的 dsh-rule-guard-0.4.2.zip(解压即用,含 README / RULES.md /
client.js / assets / 两个自测脚本)。

六、已知 / Known

  • 复核仍是软约束:措辞可以影响模型,不应视为安全边界
  • 每个送审动作仍有一次模型调用(约 2–5 秒),这是 fail-closed 的固有代价

完整变更 / Full changelog

v0.4.1..v0.4.2

v0.4.1 — 修复规则文件不生效与安装包缺文件

Choose a tag to compare

@yunling-bionic yunling-bionic released this 01 Nov 05:51

dsh-rule-guard v0.4.1

修复 0.4.0 的两处真实缺陷,并降低一处误判来源。判据未变:只判断「这一步是否在当前目标内」。

This release fixes two real defects in 0.4.0 and reduces one source of misjudgement.
The criterion is unchanged: is this step within the current goal.


一、修复:规则文件改了不生效 / Fix: editing the generated rule file had no effect

0.4.0 首次安装会把 RULES.md 写到插件数据目录,但复核只读工作区的规则文件,
数据目录那份从未进入判定材料 —— 按横幅提示去改它,等于没改。

loadRules 现在按以下顺序合并规则(三者同时生效):

① <工作区>/AGENTS.md
② <工作区>/CLAUDE.md 或 <工作区>/.dsh/rules.md
③ <插件数据目录>/RULES.md            ← 0.4.1 新增
④ 配置项 rulesFiles 里列出的文件

数据目录:Windows %APPDATA%\dsh-desktop\harness\rule-guard\,其它平台 ~/.dsh/rule-guard/。

二、修复:安装包缺文件 / Fix: the published archive was incomplete

0.4.0 的分发 zip 是手工压缩的,实际只有 cordis.patch.yml、package.json、
lib/index.js 三个文件;files 里声明的 README.md、RULES.md、LICENSE 都不在其中。
首次安装读取包内 RULES.md 必然失败,而失败被 catch 吞掉,用户既拿不到默认规则,
也看不到文档。

本版两处修正:

① 包内缺失时改用内置 DEFAULT_RULES_TEXT 兜底生成,不再静默失败
② 发行物改由 npm pack 产出(11 个文件全部在内),zip 由同一份 tar 解出后压缩

三、改进:短指令导致目标丢失 / Improved: short instructions losing the goal

0.4.0 只取最近 3 条用户消息作为目标。实际对话里常见「做吧」「接」「直接做」「继续」,
这些消息不含目标信息,模型只能猜。

0.4.1 起:若最近几条都属于这类「光答应不说明做什么」的短指令,会再向前补最近一条实质指令。

四、未改动 / Unchanged

  • 判据仍只有一条:动作是否在当前目标内
  • 判决仍为 fail-closed:复核失败、输出不可解析、判决冲突一律拒绝
  • 仍无 failMode / allowTools / 任何豁免开关
  • 缓存仍只复用「拒绝」,精确参数指纹 + 会话隔离 + 10 分钟
  • 成本不变:每个送审动作一次模型调用(约 2–5 秒)。这是 fail-closed 的固有代价,不是缺陷

升级方式 / Upgrade

dsh plugin add dsh-rule-guard

或使用本次 Release 附件的 dsh-rule-guard-0.4.1.tgz(npm 包格式)
/ dsh-rule-guard-0.4.1.zip(解压即用,含 README、RULES.md、client.js、assets)。

反馈致谢 / Thanks

上述前两条问题由用户实测反馈指出,均已在代码中核实并修复。

完整变更 / Full changelog

v0.4.0..v0.4.1

v0.4.0 — 判据改为目标一致性,fail-closed

Choose a tag to compare

@yunling-bionic yunling-bionic released this 31 Oct 17:26

dsh-rule-guard v0.4.0

本版重写了复核判据与判决口径,并补齐客户端提示、通用规则文件与中英双语文档。

This release rewrites the review criterion and verdict handling, and adds a client-side notice,
a general rules file, and bilingual documentation.


变更摘要 / Summary of changes

一、判据重写 / Review criterion rewritten

0.1.x 0.4.0
判据 是否写文件(写特征匹配) 动作是否在用户当前目标内
风险是否作为判据 是 否
失败处理 fail-open(异常则放行) fail-closed(异常则拒绝)
可配豁免 allowTools / failMode 等 无

二、送审范围 / Review surface

  • 行为类工具:写文件、非只读 shell、装包、起服务、网络请求、派子代理、定时任务、桌面操作、office 落盘
  • 未知工具默认送审;读取工作区外路径送审
  • 免审:纯读取且在工作区内;只读 shell 白名单
  • 复核载荷包含脚本正文开头 4 KiB,避免"只审命令行"

三、防操纵与一致性 / Anti-manipulation and consistency

  • 模型自述字段(description 等)不进入判定材料
  • 目标段与待审数据分区,仅对"待执行行为"的参数与脚本正文做注入检测
  • 超限不静默截断:先拒绝,不截断后判 allow
  • 路径 realpath 规范化(junction、符号链接、8.3 短名)
  • 编码命令、iex、动态求值等不可见执行形态直接拒绝
  • 缓存仅复用「拒绝」,精确参数指纹 + 会话隔离 + 10 分钟

四、新增 / Added

  • client.js:首次安装提示改为客户端横幅(slot shell.overlay,可关闭,只弹一次),中英双语
  • RULES.md:通用复核规则十节;首次运行生成到标准插件数据目录,用户改动不被覆盖
  • scripts/first-run-selftest.mjs:数据目录解析与首次生成的验证脚本
  • README.en.md:英文文档;README.md 顶部加语言互链
  • 数据目录:Windows %APPDATA%\dsh-desktop\harness\rule-guard\,其它平台 ~/.dsh/rule-guard/

五、移除 / Removed

所有可能使复核失效的开关:failMode、allowTools、reviewReadsOutside、readRoots、
日志路径覆盖。配置只允许加严,不允许放宽。


验证 / Verification

项目 结果
行为与边界用例(内联) 15/15、14/14、9/9;缓存安全 8/8
运行时:读取工作区外 拒绝
运行时:工作区内读取 放行
运行时:偏离目标动作 拒绝,重放命中 cache-hit-deny
脚本写入检测(py -c 内 open(...,'w')) 拒绝,且文件未创建
node --check(lib/index.js、client.js) 通过
首次安装横幅 重启后出现,关闭后刷新不再出现

已知限制 / Known limitations

  • 复核为软约束:措辞仍可能误导判定,不应作为安全边界
  • 每次送审增加一次模型调用,约 2–5 秒延迟与少量 token 开销
  • 自测集中有 3 条断言针对已删除的旧后门(allowTools 免审、未知工具免审、failMode 放行),尚未清理
  • 审计日志中存在少量自测噪音记录

升级说明 / Upgrade notes

  • 版本从 0.1.x 升级到 0.4.0,package.json 与代码内 VERSION 一致
  • 规则文件位于数据目录而非安装包内,升级不覆盖用户改动
  • 判据变化会改变既有行为:模糊指令将被拒绝,需在指令中写明"做什么、在哪、为什么"

完整变更 / Full changelog

da5554a..f65b733