feat(chv): 对齐 Muse P6 privsep worker + 确定性安全检查层
- cloud/chv/privsep.py(新):Gitea worker 注册表(凭证白名单只含 GITEA_TOKEN)+ 类型化请求/响应(request_id 绑定、64KB 上限)+ Unix socket 客户端(超时/崩溃 -> 类型化失败 WorkerRefusal)+ 客户端白名单校验 - cloud/chv/safety.py(新):UntrustedData 来源标记 + InjectionScanner 确定性规则(block/flag/allow,中英)+ redact_secrets + AuditLogger(只记指纹,不记值)+ audit_inference_request/response - chv-guest/chv-gitea-worker.py + .service(新):systemd 沙箱化 worker(SO_PEERCRED 只放 root,仓限 ~/workspace,git 只配 authd helper,绝不持 token;输出先扫描再返回) - chv-guest/chv-sync-worker-client.py(新):agent 侧薄 CLI - chv-guest/chv-sync.sh:pull/push/status 有 socket 时走 worker, 否则旧路径 + stderr 警告(过渡兼容) - cloud/chv/executor.py:_run_guest 前后加推理边界审计钩子 (best-effort) - docs/chv-muse-p6-gap.md(新):差距表 + 覆盖边界 + 真机待验证清单 - docs/chv-production-readiness.md:§15 - cloud/tests/test_chv_muse_p6.py(新):43 项 测试:新测试 43/43;全量 cloud 套件 1910 OK(skipped=9);mypy 在新增文件上干净(剩余 4 处为基线旧错 executor.py:1396/1401、 marker_tools.py:142,未动)。 真机验证:未做,排队在 round-11 之后,清单见 docs/chv-muse-p6-gap.md §4。
This commit is contained in:
1 parent
06c3e172fe
commit
81e4eaf4db
10 files changed
+2071
No files matched your search
@@ -0,0 +1,157 @@
|
||||
# 对齐 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:<repo>`)随数据走;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/<pid>/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 的全链路。
|
||||
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 信息样本)。
|
||||
Reference in new issue
Block a user