[Bug][Mimosa 1.0.3] Bash PreToolUse denial is not recorded in finding ledger and has no scoped suppression
Nobody has claimed this yet.
- Dominant language
- No language data
- Stars
- 22
- Forks
- 1
- PR merge metrics
- No merged PRs in 30d
Description
环境
- 事发日期:2026-08-31
- ZCode Desktop / Windows 11(10.0.26200 x64)
- ZCode Desktop 版本:v3.10.2(2026-09-02 关于页捕获;未单独核实 2026-08-31 事发时是否同版)
- Mimosa:
mimosa@zcode-plugins-official 1.0.3 - 场景:PreToolUse / Bash 安全门
- 相关先例(非重复):#300 —— suppression / 误报豁免机制请求
问题概要
Mimosa 1.0.3 对一类合法、经过人工审查的 Bash 变更操作进行阻断时,观察到与正常 finding 流程不一致的现象——拒绝发生但 ledger 零记录。其底层机制(独立的快速拒绝路径 / 异步落账失败 / 组件差异)未定位,「快路径」在本文其余部分只是这一现象的工作假设,不是机制结论:
- Bash 调用在 PreToolUse 阶段被拒绝;
- UI / agent 收到的拒绝理由属于「Bash 直接写源码」守卫族(完整逐字消息未保存,本文不作超出该守卫名族的转述);
- 但该拒绝没有写入
.mimosa/finding-ledger/v1/events; - 因此没有
findingId、ruleId或其他稳定审计锚点; - Mimosa 1.0.3 同时没有针对该类拒绝的 project/path/rule/exact-command scoped suppression;
- 结果是:经人工审查确认安全的操作无法执行,用户又无法通过可审计的窄域例外处理误报,只能选择关闭整个 Mimosa——这会把一个局部误报扩大成全局安全控制空窗。
实际场景
目标操作是创建一个新的 Python virtual environment,并仅从本地、已哈希钉定的 wheelhouse 做离线安装。
执行票已经包含以下限制:
- 创建目标前要求目录 EXACT-ABSENT;
- requirements lock 在任何变更动作前做 SHA-256 gate;
- 安装使用
--no-index; - 使用
--require-hashes; - wheelhouse 为唯一 package source;
- pip 配置和环境注入被隔离;
- 安装后执行版本门、
pip check; pip freeze使用 isolated/config-null 模式;- freeze 结果通过
pipefail管道进入只读 verifier; - verifier 对 lock 与 freeze 做双向 EXACT set equality;
- 不使用
--no-verify; - 不修改项目源码、全局 Python 或 user site-packages。
该执行票仍被 Mimosa Bash gate 在 PreToolUse 阶段拒绝。
行为面最小诊断
为避免通过“改写命令绕过守卫”,只做了若干无写入、无网络的只读探针。
以下单元素均未触发同一拒绝:
- pipe +
python -c python -c中只读open(..., "rb")- pipe +
python script.py python -m venv --helppip install --help
因此没有对具体单变量做过度归因。
目前只能确认:
触发面收敛到 mutating-form
python -m venv <target>/pip install ...或二者组合。
没有执行额外的真实写单变量探针,因为这样会增加副作用而不能解决 suppression 缺失的问题。
finding-ledger 取证
对当天 finding-ledger/v1/events 做了脱敏、metadata-only 检查。
当天已有的 reasonCode=deny finding 均能正常取得:
projectRelativeFileruleIdreasonCodeline
但它们对应的是另一条 Write scan-hook 事件。
本问题中的两次 Bash PreToolUse 拒绝:
- 没有对应 finding event;
- 没有 findingId;
- 没有 ruleId;
- 无法在 ledger 中建立“本次拦截 → 某条规则”的审计链。
因此无法使用 finding 作为 suppression 锚点。
为什么这是安全问题,而不仅是体验问题
安全门出现 false positive 并不可怕,关键是必须能够:
- 解释为什么拦截;
- 留下可追溯 finding;
- 允许用户对已经人工复核的单条/单规则/单路径误报做窄域处置;
- 保持其他安全规则继续启用。
当前行为同时缺少第 2 和第 3 项。
这会导致用户只能二选一:
- 永久无法完成合法操作;
- 或关闭整个 Mimosa。
后者反而扩大攻击面。
期望行为
建议至少实现以下两项。
1. 所有 deny 都进入统一 finding / audit ledger
即使是 PreToolUse 的快速拒绝,也应生成最小事件,例如:
- event/finding id
- rule id
- reason code
- tool type
- project-relative target(适用时)
- evidence hash
- timestamp
- final verdict
敏感 command/evidence 可哈希或脱敏,不要求明文记录。
2. 提供可审计的 narrow suppression
建议支持一种或多种:
- findingId suppression
- rule + project-relative path suppression
- exact-command / command-hash one-shot approval
- project baseline 文件
- 带理由与 expiry 的 scoped exception
需要明确避免只有“Disable Mimosa”这种全局开关。
与 Issue #300 的关系
#300 与本报告属于同一产品区域、同一 suppression 缺口,但失败模式不同——是相关先例(related precedent),不是重复报告:
- #300(仍 open):suppression 能力缺口——请求误报豁免机制,并记录 sanitizer/参数化建模类误报「现有改写无法消除、缺少 suppression 通道」;
- 本报告:deny-event 可观测性 / finding-ledger 一致性问题——某些 Bash PreToolUse deny 根本不进入 finding-ledger,因此即使未来 suppression 以 finding/rule 为锚点实现(#300 的方向),这类不落账的 deny 仍可能无法使用该机制。
建议在实现 #300 时同时统一这类不落账 denial 的审计事件模型。
当前 workaround
目前没有安全的 scoped workaround。
我们选择:
- 保持 Mimosa 开启;
- 不使用 subprocess 等方式包装/绕过;
- 不全局关闭守卫;
- 将该迁移步骤标记为 HOLD;
- 等待官方规则修复或提供 scoped suppression 后再恢复。
如果需要,我可以提供:
- 脱敏后的执行票;
- 探针矩阵;
- finding-ledger metadata 对照结果;
- 精确的版本/环境信息;
均可在不披露凭据的情况下提供。
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the PreToolUse/Bash denial path and the .mimosa/finding-ledger/v1/events evidence described here; no source files or tests are identified. Confirm whether these denials bypass the finding ledger, then define completion as every deny having an auditable event and a narrow, non-global suppression path, with regression coverage for both.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- bash, python
- Domain
- security, tooling
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100