zai-org / zai-org/feedback

[插件mimosa] Git 门禁集成缺陷:排除项被忽略、误报无处置途径、卸载不生效(无出口闭环)

Open
#329 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

priority: P2
Dominant language
No language data
Stars
22
Forks
1
PR merge metrics
No merged PRs in 30d

Description

环境:macOS 15(darwin 27.0.0, arm64),ZCode CLI + zcode-plugins-official/mimosa 1.0.3。项目是 Bun + TypeScript 的 Web Components 库,带一个由已审计源码构建生成的压缩文档产物(docs/assets/main.js,gitignore 的生成输出)。

摘要:五个集成缺陷叠加,导致 agent 侧的每次 git commit 都被一组既无法修复、也无法处置、还关不掉的 finding 永久阻断。每个行为单独看都有其道理;合在一起构成一个没有出口的闭环。

1. commit 门禁忽略 threatModel.exclusions

.mimosa/security-policy.json 声明了 threatModel.exclusions: ["docs/**", "docs/"]policy checkthreat-model check 均通过;目录审计遵守该排除项。但 L3 commit 门禁(PreToolUse 拦截含 git commit 的 Bash 命令)不遵守:它扫描被排除的路径并硬阻断 —— 我们的案例中是生成产物 docs/assets/main.js 内的 2 个 high 与 7 个 medium。

期望:门禁与审计遵守同一套排除项,或文档说明门禁另有单独的排除机制。

2. 无法修复的误报没有处置途径(与 #300 呼应)

mimosa validate <finding-id> 拒绝一切非 fixed_static 状态的 finding:

✗ 只有 fixed_static finding 可进入运行复验;当前为 blocked

mimosa-ignore 注释在门禁模式下又被 --no-ignore-comments 禁用(对不可信代码这样设计本身是合理的)。于是生成产物上的误报没有任何出口:产物每次构建都从已审计的源码重新生成,finding 随之回来,而没有任何机制能把它标记为「已人工复核」。具体案例:我们产物里唯一的 exec( 是分词循环中的 RegExp.prototype.exec,整个文件不含任何 SQL 关键字 —— 两条分别被报成命令注入与 SQL 注入,依据只是压缩后的标识符名。

期望:同 #300 请求的密封处置流(finding 级误报判定 + 理由,写入 ledger,门禁遵守)。补充一点:在门禁遵守排除项/处置结果之前,validate 至少应能受理 blocked 状态的 finding。

3. git-gate uninstall 关不掉真正拦截的那一层

mimosa git-gate uninstall 报告成功并声称恢复了安装前的 hook;随后 ZCode 的 PreToolUse Bash 钩子仍以完全相同的 finding 阻断 git commit。值得注意:前后 .git/hooks 里都不存在任何 Mimosa hook —— 真正拦截的是插件注册的 ZCode 钩子层,uninstall 并未触及。

期望:uninstall 停用真正拦截的那一层;或文档说明 ZCode 钩子层需另行禁用插件。

4. 文件扫描中的 advisory 到门禁侧变成阻断 high

mimosa scan <file> --json 将入口点类 finding(如 runCommand 是 command-injection 入口)标为 "advisory": true;门禁的阻断信息却把同一批 finding 计入「6 个高危」并硬阻断。同一 finding 两套阻断语义,使用者无法从扫描输出推断什么会挡住 commit。

期望:扫描与门禁采用一致的阻断语义。

5. 结构化规则不识别任何净化器写法(已实测,与 #300 呼应)

两次实测(改动后均重新扫描确认):

  • fetch(dynamicUrl) 调用前一行内联 new URL() + 同源 + http:/https: 协议校验,仍报 SSRF(CWE-918)—— 而且这是浏览器端代码,本不存在服务端请求伪造的语境。
  • 在同一函数内对每个动态元素做严格白名单校验(组件名 kebab-case 正则;透传参数逐个检查 --flag / --flag=value 形态),spawn(prog, computedArray) 仍报 CWE-88。

一个文档明示用途就是透传任意 Playwright 参数的 CLI 测试跑批器,不放弃自身功能就无法满足前一条规则;构建脚本以静态参数 spawn bun build 同理。这与 #300 在 Python/SQLAlchemy 侧观察到的「守卫不被识别为净化器」是同一类问题。

期望:文档化一批被识别的净化器模式(URL 同源/协议校验、白名单校验)并使其切断污点边;在此之前,「修复后重扫」对合法的工具代码不可执行。

6. 次要:钩子把状态写进嵌套目录,破坏基线捕获

某次钩子以别的工作目录运行,在项目内创建了 .agents/skills/<skill>/.mimosa/hook-state/*。此后每次 Stop 钩子的基线捕获都报 snapshot_error_count: 2baseline_snapshot_unreadable —— 600 权限的状态文件在捕获期间自身仍在被写),所有批次记为 inconclusive/partial,进而又使 validate 拒绝运行(「finding ledger 为 partial」)。删除该杂散目录后恢复正常。建议钩子状态固定写入工作区根目录,并把自身状态目录排除在基线捕获之外。


建议优先级:1 + 2 是「无出口闭环」的核心;3 是打不开的逃生门;4–6 可独立处理。与 #300 的关系:#300 从功能角度请求豁免机制与净化器建模,本 issue 补充门禁集成侧的缺陷证据 —— 特别是「已声明且校验通过的排除项在门禁被忽略」与「uninstall 不生效」两点,各自独立成立。

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the reported behavior with .mimosa/security-policy.json, docs/assets/main.js, and the stated mimosa policy, scan, validate, and git-gate commands. Compare audit exclusions, advisory handling, finding validation, uninstall behavior, and hook-state snapshots; done requires the affected layers to apply consistent rules and provide a usable resolution path.

Written by the indexing model from the issue text.

Assessment

Tech stack
git, typescript
Domain
cli, devtools, security
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.