# 对齐 Muse P6 差距表:privsep worker + 确定性安全检查层 依据:`~/workspace/research_notes/meta-muse-ai-architecture-20261101-0755/report.md` (官方以 Meta security.muse.ai 2026-09-08 为准;第三方拆解只作参考, 逆向细节不得写成官方架构)。Muse 模型相关句(官方): - 内置连接器的执行分离:单元内的连接器 CLI 只解析参数、打开调用者 已有权访问的文件、通过 Unix socket 传递类型化参数与文件描述符; 真正业务逻辑由 systemd 沙箱化的 privsep worker 执行;每个 worker 由 cgroup 标识、有明确凭证白名单(日历 worker 不能仅改参数就索取 邮件凭证)。 - 纵深防御分层:模型层训练识别提示注入;Harness 层外部数据进入模型 上下文时标注为“不受信任输入”;独立分类器层多组提示注入检测分类器 并行运行,覆盖经文件与工具调用进入模型上下文的全部外部数据; 确定性边界层(运行时单元限制系统访问、privsep 限制哪些代码可见 哪些凭证、authd 执行 ACL、Sentinel 评估每个动作与全部网络出口)。 - hatch-safety:独立模型与分类器检查进出核心模型推理的请求/响应。 本轨范围只限 P6:privsep worker(先做 Gitea 同步一个连接器)+ 确定性安全检查层(标注 + 审计 + 规则版注入检测)。不碰 P1(常驻 VM、 气球、vsock)、不碰 P2(nspawn 单元、broker、浏览器子代理)、不碰 P3(authd/sentinel 本体——只读、不重写、不改接口)、不碰 P4(浏览器 完全对齐)、不碰 P5(Sentinel 纵深、eBPF 污点)。分支 `feat-chv-muse-p6`(从 `feat-chv-cover100` 分出,基线 HEAD `06c3e17`)。 ## 1. 现状 vs Muse | 项 | 现状(实测/代码为准) | Muse 目标 | 本轨做法 | |---|---|---|---| | 连接器执行位置 | Gitea 同步逻辑直接跑在 agent 可达的进程里:宿主执行器经 SSH 调客内 `chv-sync`(bash),P2 的 broker 再以 chv 身份直跑 `chv-sync` 子进程。`chv-sync` 一个进程里既解析参数、又读凭证、又跑 git、又碰网络——没有执行分离 | 单元内 CLI 只解析参数、传类型化参数与文件描述符;真正业务逻辑由 systemd 沙箱化的 privsep worker 执行;每个 worker 由 cgroup 标识 | 客内新增 `chv-gitea-worker` 守护进程(systemd 单元,见 §2):Gitea 同步的 git 业务逻辑(clone/pull/push/status 的 git 调用)只在 worker 里跑;agent 侧(broker/`chv-sync`)只剩薄 CLI——解析参数、发类型化 JSON 请求、走 Unix socket、拿类型化响应。worker 崩溃/超时只返回类型化失败,不拖垮 agent(失败分类与审计) | | worker 身份与凭证白名单 | 无 worker 概念,无白名单。`chv-sync` 直接读落盘的 `.git-credentials`(旧路径)或走 P3 helper(新路径),调用方改参数就能让它对任意仓库跑 git | 每个 worker 由 cgroup 标识、有明确凭证白名单(改参数也索取不到别的凭证) | worker 注册表只认一个 worker:`gitea`,凭证白名单只含 `GITEA_TOKEN`,操作只含 pull/push/status/ping,仓库只限 `~/workspace` 下。白名单三处 enforce:① 客户端(`PrivsepClient`)发请求前校验,越权请求不出门;② worker 服务端再校验一次(不信任客户端);③ 凭证获取本身不经过 worker——git 经 P3 的 credential helper 向 authd 按次取凭证,authd 按 {连接器, 主机, 仓库, 操作} 绑定放行,worker 改参数也拿不到别的凭证。worker 进程本身绝不持有 token 值(argv/env/日志/审计里都没有) | | worker 的网络出口 | `chv-sync` 的 git 直连 Gitea;出口只靠 Tinyproxy 白名单 + 宿主防火墙(第三棒落地中),无每动作审批 | Sentinel 评估每个动作与全部网络出口 | worker 的 git 只配 P3 helper + 只连配置的 Gitea 远端;每次取凭证前 authd 已先过 Sentinel 评估(P3 机制,本轨不重复造);worker 的 systemd 单元再叠加 `RestrictAddressFamilies` 与网络命名空间收紧。网络层强制(eBPF 拦截)是 P5 的范围,本轨不宣称 | | 外部数据进模型上下文 | 无标注。Gitea 拉回的提交信息、文件名、diff 内容经 `chv-sync` 输出原样回到 agent 回合,codex 自己拼上下文,我们这边不区分“用户写的”与“远端拉回的” | Harness 层:外部数据进入模型上下文时标注为“不受信任输入” | `cloud/chv/safety.py`:`UntrustedData` 携带来源标记(`source`,如 `gitea:`)随数据走;worker 的 git 输出在返回前先过扫描 + 打上来源标记;`PrivsepClient` 把标记带回调用方。注意诚实边界:codex 在客内自己拼上下文,我们的标注能保证的是“经我们这条连接器链路回来的数据都带标记”,不是“codex 一定会读标记”——后者须 codex 侧配合,不在本轨 | | 提示注入检测 | 无 | 独立分类器层:多组提示注入检测分类器并行,覆盖经文件与工具调用进入上下文的全部外部数据 | 确定性规则版 `InjectionScanner`(不是模型分类器,不冒充):指令性文本规则(中英)、命令/URL 注入模式、可疑拼接模式;分级 `block`/`flag`/`allow`。`block` 只给高置信模式(shell 执行链、直接指令覆盖);`flag` 给中置信(指令性文本、可疑 URL),命中即标记复核、不自动执行后续写操作;`allow` 其余。规则覆盖边界单列在 §3.3 | | 请求/响应审计(hatch-safety) | 执行器 `_emit` 只审 VM 生命周期事件(VM 名/路径/URL/kind,不含 key 值);进出模型推理的请求/响应无审计 | hatch-safety 检查进出核心模型推理的请求/响应 | `safety.audit_inference_request/response`:在执行器派发边界(`_run_guest`,任务 → 客内 codex;结果回)记审计——只记任务 id、kind、内容指纹(SHA-256 前 16 位)、长度、扫描 verdict;密钥与 token 值绝不进审计(先过 `redact_secrets` 再记,审计失败 best-effort、不中断任务,沿用 `_emit` 既定语义) | | 与 P3 的接线 | P3 已做完(a90cf78):authd 替身凭证 + Sentinel 最小审批 | privsep worker 的凭证只走 authd 替身;worker 出口只走 Sentinel 审批 | worker 的 git 一律配 `-c credential.helper=/usr/local/bin/git-credential-chv-authd -c credential.useHttpPath=true`(P3 的 helper 路径与 P3 修过的 path 坑),不用 `.git-credentials`;helper 缺失时 worker 直接拒绝(fail-closed),不回落读 token。Sentinel 评估发生在 authd 放凭证前(P3 机制),worker 不另造决策器。本轨不 import P3 的模块(基线 06c3e17 里没有 P3 代码):接线走已定的文件/socket 协议,合入时由集成轨接通;本轨测试用替身(fake)实现同一协议 | ## 2. 改了什么(本轨交付物) - `cloud/chv/privsep.py`(新,叶子模块,标准库):worker 注册表 (本期只 `gitea`)+ 类型化请求/响应(`WorkerRequest` / `WorkerResponse`,JSON 行,≤64KB)+ `PrivsepClient`(Unix socket 客户端:超时、worker 崩溃 → 类型化失败、响应校验、返回前过安全 扫描)+ 客户端白名单校验(越权请求不出门)+ cgroup 标识读取 (`/proc//cgroup`,审计用)。 - `cloud/chv/safety.py`(新,叶子模块,标准库):`UntrustedData` 来源标记 + `InjectionScanner`(规则版,中英指令模式、命令/URL 注入模式、可疑拼接,分级 block/flag/allow)+ `redact_secrets` (token/key/口令模式脱敏)+ `audit_inference_request/response` (只记指纹与 verdict,不记值;失败 best-effort)。 - `chv-guest/chv-gitea-worker.py`(新,标准库守护进程):Unix socket `/run/chv-gitea/worker.sock`(0700 目录、0600 socket);SO_PEERCRED 只放行 root(broker 走 root 连);操作白名单 pull/push/status/ ping;仓库只限 `~/workspace` 下(realpath + commonpath);git 以 chv 身份跑(`runuser -u chv`,文件归属不变),argv 里只配 credential helper、绝无 token;输出先过 `safety` 扫描 + 来源标记 再返回;超时 300 秒;异常只断本连接。 - `chv-guest/chv-gitea-worker.service`(新):systemd 单元(root 运行, 单元外;`ProtectSystem=strict`、`PrivateTmp`、`NoNewPrivileges`、 `CapabilityBoundingSet=` 空、`RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6`、`SystemCallFilter=@system-service`、读写路径只限 `/home/chv/workspace` 与 `/run/chv-gitea`)。 - `chv-guest/chv-sync-worker-client.py`(新,标准库薄客户端): `chv-sync pull/push/status` 在 worker socket 存在时改走 worker (发类型化请求、原样回显 worker 的 stdout/stderr、按 worker 的 returncode 退出);socket 不存在时走旧的直接路径 + stderr 警告 (过渡兼容,见诚实边界第 4 条)。 - `chv-guest/chv-sync.sh`:pull/push/status 三处改走上述客户端 (有 socket 时);boot 不动(cloud-init 时的一次性 clone,仍按 P3 后的 helper 路径走)。 - `cloud/chv/executor.py`:`_run_guest` 前后加推理边界审计钩子 (best-effort,不改结果、不中断任务)。 - `cloud/tests/test_chv_muse_p6.py`(新):见 §3 的覆盖清单。 - 镜像集成(只留接入说明,不改 `chv-guest/build.sh`,与 P2/P3 同款 规矩,合并时由集成轨带进镜像): `--copy-in chv-guest/chv-gitea-worker.py:/usr/local/bin/`、 `--copy-in chv-guest/chv-sync-worker-client.py:/usr/local/bin/`、 `--copy-in chv-guest/chv-gitea-worker.service:/etc/systemd/system/`、 `--copy-in cloud/chv/privsep.py:/usr/local/lib/chv-gitea/cloud/chv/`、 `--copy-in cloud/chv/safety.py:/usr/local/lib/chv-gitea/cloud/chv/`、 `--copy-in cloud/__init__.py:/usr/local/lib/chv-gitea/cloud/`、 `--copy-in cloud/chv/__init__.py:/usr/local/lib/chv-gitea/cloud/chv/`、 `--run-command 'chmod +x /usr/local/bin/chv-gitea-worker /usr/local/bin/chv-sync-worker-client'`、 `--run-command 'systemctl enable chv-gitea-worker || true'`、 `99-chv-sync.cfg` 的 runcmd 在 `chv-sync boot` 之前加 `systemctl start chv-gitea-worker || true`。 另:worker 依赖 P3 的 helper(`/usr/local/bin/git-credential-chv-authd` + authd socket `/run/chv-authd/authd.sock`),P3 的接入说明里的 copy-in 须一并落地,否则 worker 的 git 拿不到凭证、直接拒绝。 ## 3. 测试覆盖与诚实边界 ### 3.1 测试覆盖(`cloud/tests/test_chv_muse_p6.py`,全覆盖以下每一项) - privsep 协议:未知操作/未知连接器/仓库越界(`..`、workspace 外) 被拒;响应格式不对被拒;超时与 worker 崩溃(socket 半路关闭) → 类型化失败 `WorkerRefusal`(不是裸 socket 异常、不拖垮调用方)。 - 白名单:客户端越权请求(未知操作、未知连接器)不出门;服务端 再拒一次;worker 的 git argv 里只有 helper 配置、绝无 token 值。 - worker 真 socket 回路:pull/push/status/ping 全通(假 git runner, 不跑真 git、不联网);git 输出先扫描 + 打来源标记再返回。 - 安全检查层:每条规则至少一个 block 用例、一个 flag 用例、一个 allow 用例(含中英);真实 git 输出样式(commit 信息、URL、正常 英文)不误报;审计记录里扫不到任何测试密钥值;脱敏覆盖全部密钥 模式;`check_context_input` 的 block 即阻断、flag 即标记复核。 - 推理边界审计:请求/响应审计只含指纹与 verdict;审计回调失败不 中断任务。 ### 3.2 架构测试约束 新模块须过 `test_no_chv_function_over_50_lines`(函数 ≤50 行)与 `test_public_api_fully_annotated_and_no_any`(公共 API 全注解、无 Any)。 ### 3.3 确定性检查层能拦什么、不能拦什么(单列) 能拦:字面指令覆盖(中英常见写法)、shell 执行链(`curl|sh`、 `$(...)`、反引号命令替换、`;` 拼接危险命令)、可疑 URL(非 https、 IP 字面量、userinfo 含口令、`data:`/`javascript:`)、把指令藏在 分隔线后的可疑拼接。不能拦:改写过的指令(同义词替换、拆字、编码、 Base64、零宽字符)、藏在图片/附件/二进制里的指令、需要理解上下文 才能判定的社会工程式诱导、模型自身的幻觉与误读——这些要模型分类器 (hatch-safety 同款)才有机会拦,规则版拦不住,不得宣称已覆盖。 规则是确定性的:同一输入永远同一 verdict,可复现、可测试;误报率 靠 allow 用例钉住,新增规则须先补用例。 ### 3.4 诚实边界(本轮不宣称的东西) 1. **本轨不 import P3 的模块**:基线 06c3e17 里没有 P3 的 authd/ sentinel 代码,本轨的接线走文件/socket 协议(helper 路径、 authd socket 路径、Sentinel 评估发生在 authd 放凭证前)。本轨 测试用替身实现同一协议;与 P3 代码的真正接通发生在合入时, 须由集成轨跑通 worker→helper→authd→git 的全链路。 **已接通(round-12,本地部分)**:`cloud/tests/ test_chv_muse_round12.py`(WorkerProtocolTest)用真 PrivsepClient + 真 worker server + 真 git status 跑通,worker 的 git argv 含真实 P3 helper 与 useHttpPath、argv/env/审计 均不含 token;runuser 包装与 HTTP 拉取(需真实 gitea.tose.top + Sentinel 放行)留给真机轨。 2. **worker 跑在客内 root**:worker 守护进程以 root 身份跑在单元外 (与 P3 authd 同款选择),git 子进程再以 chv 身份跑。root worker 本身不受单元隔离保护——它的隔离来自 systemd 沙箱 + socket 白名单 + 不持凭证;客内 root 万能仍是 P2 的边界,不是本轨能修的。 3. **网络层强制不是本轨**:worker 的出口收紧靠 Sentinel 评估 (authd 放凭证前)+ 只配 helper 的 git + systemd 沙箱;eBPF cgroup 拦截 + LSM 污点传播是 P5 的范围。不得把本轨写成“出口已 全部经 Sentinel 强制”。 4. **过渡兼容留了旧路径**:worker socket 不存在时 `chv-sync` pull/push/status 仍走旧的直接路径(只多一句 stderr 警告),为 的是旧镜像不被一次改断。旧镜像退役后应删掉该回落,改为无 worker 即 fail-closed;删除前不得声称“旧路径已关闭”。 5. **无真机验证**:本轮全部是代码 + 本地单测(含 worker 真 socket 回路 + 假 git runner)。真机待验证清单见 §4。 ## 4. 真机待验证清单(等测试机空闲,排队在 round-11 之后) - worker 在 lite12 镜像里的启动时序(须在 broker/`chv-sync` 调用 之前就绪;与 P3 authd 的启动顺序关系)。 - worker 的 systemd 沙箱在真机上生效(`systemctl status`、cgroup 路径、受限调用被挡的表现)。 - broker → worker → helper → authd → git 全链路在真机上跑通 pull/push(真 Gitea、真 token 替身)。 - worker 崩溃后 agent 侧只收到类型化失败、任务不炸(杀 worker 进程复现)。 - 安全扫描在真机 git 输出上的误报率抽查(真实 commit 信息样本)。