Skip to content

fix(#21-#24) 多方案-sol-a:全面修复 4 个 issue - #25

Closed
Nicholas023 wants to merge 4 commits into
mainfrom
sol-a
Closed

Nicholas023 wants to merge 4 commits into
mainfrom
sol-a

Conversation

@Nicholas023

Copy link
Copy Markdown
Owner

概述

独立修复 dsh-code-review 的 4 个 issue(#21/#22/#23/#24),未触碰引擎 Go 源码与生产目录。每个 issue 单独提交,commit message 遵循 fix(#NN): ... 风格。

逐 issue 修复

fix(#21) — src/model-provider.js(L62-78)

  • 问题:loadProfileLlmConfig() 的 catch 分支静默 return null——js-yaml 依赖损坏/缺失时路由表为空、评审 0.0s 失败且失败文案不指向原因,排查无从下手。
  • 修复:catch 分支捕获 error 并 console.error 输出可诊断信息(含真实错误原因),保持 return null 契约不变(不抛、不改返回值;运行态降级链与 scripts/switch-model-e2e.mjs 的 check('解析出端点', !!ep) + ep?.keyEnv 安全链均依赖此契约)。
  • 验证:隔离目录移走 js-yaml 实测——stderr 输出「js-yaml 加载失败…原因:Cannot find module 'js-yaml'」,createModelSource 不抛异常,resolveProvider('session') 返回 null(契约保持)。

fix(#22) — scripts/engine-e2e-smoke.mjs(L114-122)+ scripts/sensitive-e2e-smoke.mjs(L105-125 区域)

  • (a) engine-e2e:key 未解析(undefined)时旧代码仍构造 OCR_LLM_TOKEN: key(成字面量 'undefined')并 spawn 引擎空等 180s 必败。新增 else if (typeof key !== 'string' || key.length < 8) 短路分支,输出 check('跳过引擎调用(key 缺失)', true, ...) 显式说明跳过原因,无 key 环境不再空等、不误报失败。
  • (b) sensitive-e2e:引擎输出泄露断言原嵌套在 if (candidates.length > 0) 报告分支内——reviewOnce 静默失败且报告未落盘时整段跳过 = 假绿。已提出为独立断言:text 非空时断言无泄露;为空时显式失败归因(「评审返回空文本,无法验证送审链路」,与上方「评审返回非空文本」失败项叠加指向同一根因),杜绝静默跳过。
  • 验证:e2e-sensitive 执行时报告未落盘(引擎缺失环境),「引擎输出未含 .env 内容」断言仍独立执行并输出结果(修复前会被跳过)。

fix(#23) — dsh-plugin.json(3 处权限声明)+ src/set-config-tool.js(L130-190 report_dir 校验块)

  • 采用深度:声明 + 代码级校验双管齐下(对比点里的「保守=仅声明」方案不选用)。
  • 理由:① dsh-plugin.json 是权限声明,若声明「写入前校验」而代码不实现,承诺落空——声明与实现必须一致;② engine_bin 已有同风格写前校验(L129-140)作样式参照,report_dir 补齐后两字段口径统一;③ 风险可控:set-config 测试只覆盖查询与 review_model 写入、e2e 各脚本直接构造配置不经此 execute,加校验不回退既有测试。
  • dsh-plugin.json 三处承诺:fs.write 补「写入前校验:须为用户 home 下绝对路径,解析符号链接后确认无目录遍历逃逸」;process.spawn 补「engine_bin 须为绝对路径,且写入前校验文件存在、非符号链接、非 setuid 位」;credentials.read 补「凭据仅用于 API 调用,绝不写入日志或评审报告」。
  • set-config-tool.js 代码级校验(report_dir):① ~ 展开(与 report.js expandHome 同口径);② resolve 规范化后必须位于 home 下(win32 忽略大小写前缀判断);③ 对最近存在的祖先做 realpath 后拼接不存在的后续段,防符号链接逃逸;④ 已存在但非目录拒绝;⑤ 落盘规范化绝对路径(expandHome 幂等);⑥ 被拒只剔除该字段(与 engine_bin 同「逐字段合并」语义),整单只剩被拒字段时整体拒写。
  • 验证:7 用例全过——~ 展开/绝对路径合法写入且落盘绝对路径;home 外路径、home 外会话目录下的相对路径被拒(单字段整体拒写、多字段字段级拒写);空串清空恢复默认。

fix(#24) — src/sensitive-list.js(4 处)

  1. r6 token 词边界(L40):tokens? 后加 (?=[._-]|$) 显式词边界——tokenizer-decoder.yml 这类「token 词段后接普通字符」从结构上锁死不误伤。
  2. r2/r9 覆盖重叠归一(L31/L60):r2 收紧为「点开头的 secret 隐藏文件 + 锚定」(.secrets/.my.secret/.secrets.yml 保持命中),r9 加 (?!.) 负向前瞻只管「非点开头词段」——两行职责互斥。
  3. r4 凭据扩展名锚定(L34):尾部 (\.|$) → .env 式 (\.[^/]+)?$,扩展名后只能跟一个后缀段并到行尾。
  4. buildSensitiveBlock 清洗字符类(L115):补 ~ # &(删除线/标题锚点/HTML 实体起始字符,防文件名破坏报告 markdown 结构)。
  • 验证:52 样本(unit-smoke 全部敏感断言样本 + e2e-sensitive 确定性前验样本 + 探针样本)行为全部保持;npm run unit 56 项全过。

Gate 测试结果

门禁 结果 说明
npm run check ✅ exit 0 全部 node --check 语法通过
npm run unit ✅ exit 0 56 项单元自检 + file-config 16 项全过
npm run selfcheck ✅ exit 0 单元 + file-config + task-api 冒烟全过(含 dsh-plugin.json 结构校验)
npm run e2e-engine ⏱ 自然结束(exit 1) 本机无引擎二进制(bin/codecheck.exe 缺失,出 issue 范围),check 输出明确「引擎存在 — 请先把引擎二进制放到插件包 bin/」;key 缺失短路分支就绪
npm run e2e-sensitive ⏱ 自然结束(exit 1) 失败形态=报告未落盘(引擎缺失);「引擎输出未含 .env」断言独立执行(#22 修复生效);无挂死、无新增异常形态
npm run e2e-switch ⏱ 自然结束(exit 1) target=千问本地 (Ollama)/qwen3:0.6b 解析出端点 ✓(#21 契约未破坏);key/env 未注入(无 keyEnv);评审 spawn ENOENT(引擎缺失);无挂死

已知 Tradeoffs

  • e2e 失败形态 = 引擎二进制缺失:本机 bin/ 下无 codecheck.exe(引擎为 Go 源码、发布走 GitHub Release,编译产物不在本任务范围)。e2e 三件套均 5 分钟内自然结束、无挂死、无新增异常形态,符合任务判据;修复的代码路径(key 缺失短路、断言提出嵌套、null 契约)均已通过针对性验证。
  • dsh-plugin.json 权限声明缺安全校验承诺(report_dir 任意路径写 / engine_bin 任意命令执行 / 凭据无泄露承诺) #23 校验口径收紧:report_dir 现仅接受 home 下路径(解析符号链接后仍在 home 内)。若用户确实需要把报告目录放到 home 外的自定义盘位,会被字段级拒绝并回显原因(传空串可恢复默认)——这是「声明=实现」一致性的代价,可在后续按需放宽(如显式白名单)。
  • 相对路径语义:相对 report_dir 以调用方会话目录为基准解析(与 engine_bin 同基准),解析结果在 home 内即合法、在 home 外拒绝——避免隐含「写到任意 cwd 下」的注入面。

@Nicholas023

Copy link
Copy Markdown
Owner Author

整合 PR #29 已吸收本方案精华并合并(lead 实测比对后取舍)。本 PR 关闭存档,diff 仍可通过本页查看。

@Nicholas023
Nicholas023 deleted the sol-a branch October 20, 2026 07:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant