zai-org / zai-org/feedback

[Bug][Mimosa 1.0.3] Bash PreToolUse denial is not recorded in finding ledger and has no scoped suppression

Open
#481 2 comments 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

环境

  • 事发日期: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 零记录。其底层机制(独立的快速拒绝路径 / 异步落账失败 / 组件差异)未定位,「快路径」在本文其余部分只是这一现象的工作假设,不是机制结论:

  1. Bash 调用在 PreToolUse 阶段被拒绝;
  2. UI / agent 收到的拒绝理由属于「Bash 直接写源码」守卫族(完整逐字消息未保存,本文不作超出该守卫名族的转述);
  3. 但该拒绝没有写入 .mimosa/finding-ledger/v1/events
  4. 因此没有 findingIdruleId 或其他稳定审计锚点;
  5. Mimosa 1.0.3 同时没有针对该类拒绝的 project/path/rule/exact-command scoped suppression;
  6. 结果是:经人工审查确认安全的操作无法执行,用户又无法通过可审计的窄域例外处理误报,只能选择关闭整个 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 --help
  • pip install --help

因此没有对具体单变量做过度归因。

目前只能确认:

触发面收敛到 mutating-form python -m venv <target> / pip install ... 或二者组合。

没有执行额外的真实写单变量探针,因为这样会增加副作用而不能解决 suppression 缺失的问题。

finding-ledger 取证

对当天 finding-ledger/v1/events 做了脱敏、metadata-only 检查。

当天已有的 reasonCode=deny finding 均能正常取得:

  • projectRelativeFile
  • ruleId
  • reasonCode
  • line

但它们对应的是另一条 Write scan-hook 事件。

本问题中的两次 Bash PreToolUse 拒绝:

  • 没有对应 finding event;
  • 没有 findingId;
  • 没有 ruleId;
  • 无法在 ledger 中建立“本次拦截 → 某条规则”的审计链。

因此无法使用 finding 作为 suppression 锚点。

为什么这是安全问题,而不仅是体验问题

安全门出现 false positive 并不可怕,关键是必须能够:

  1. 解释为什么拦截;
  2. 留下可追溯 finding;
  3. 允许用户对已经人工复核的单条/单规则/单路径误报做窄域处置;
  4. 保持其他安全规则继续启用。

当前行为同时缺少第 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

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 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.