Files
codex-app-server/docs/chv-muse-p5-gap.md
T
host 25bcd355f8 feat(chv): 对齐 Muse P5 纵深——eBPF 污点传播 + 五档严格能力 + 对话外审批 + 默认策略
- taint.py:污点追踪器(登记/污点不可逆/子进程继承/审计)
- ebpf_taint.py:eBPF 程序源码 + 加载器(能力探测 + 降级);
  本机实测加载被 seccomp 挡(bpf() EPERM),报 blocked 不冒充
- capabilities.py:五档严格能力(一次/会话/任务/时限/永久,
  三元组绑定 + 精确匹配 + 撤销;permanent 默认不签发)
- policy.py:默认策略规则表 + 谨慎度三档(写操作与敏感路径
  永远不自动放行,规则变化审计)
- approval_channel.py:对话外审批通道(nonce + 15 分钟过期 +
  HMAC,答复一次有效,对话伪造无效)
- sentinel.py 接线:evaluate() 可选接 taint/policy/tier/scope,
  不传时行为与 P3 一致;自动放行步骤 + 档位签发回落单次;
  Capability 基类属性放宽为 Optional(None = 不限)
- 新测试 61 项;全量 cloud 套件 1958 项 OK(skipped=8)

真机待验证(未做,排队在 round-11 之后):见
docs/chv-muse-p5-gap.md §4
2026-11-06 22:25:55 +00:00

13 KiB
Raw Blame History

对齐 Muse P5 差距表:Sentinel 纵深(eBPF 污点传播 + 严格能力完整化 + 对话外审批 + 默认策略)

依据:~/workspace/research_notes/meta-muse-ai-architecture-20261101-0755/report.md (官方以 Meta security.muse.ai 2026-09-08 为准;第三方拆解只作参考, 逆向细节不得写成官方架构)。Muse 官方 Sentinel 要求:Sentinel 是 连接器动作与全部网络出口的唯一权限机构;网络出口审批在 L4 与 L7 评估主机名、解析后与最终目的 IP、端口、协议、HTTP 方法、路径、 解码后的实际请求,并有 SSRF 防护;污点出口——每个工具执行进程 初始干净,读取用户数据后变“污点”,干净且符合窄范围自动放行策略 并通过出站 URL 其他检查的请求可免打扰放行,污点或不可验证进程 失去自动放行、回到正常审批流,实现用 eBPF cgroup 程序做网络拦截 与进程归因、及挂在 LSM hook 上的 eBPF 程序做污点传播;审批是 严格能力,绑定到特定连接器/目的地与用例,支持一次性、会话级、 任务级、时限级、永久级授权,Sentinel 决定向用户呈现哪几种授权 类型,并确保后续调用与授权范围精确匹配;审批 UI 不在对话内, Sentinel 直接向客户端发审批请求、用户答复直接回 Sentinel;默认 策略只读/先前已允许/明显低风险动作可不打扰通过。

本轨范围只限 P5:Sentinel 纵深。起点是 P3(分支 feat-chv-muse-p3 提交 a90cf78,已合入本分支,见下文“起点”)。不碰 P1(常驻 VM、 气球、vsock)、不碰 P2(nspawn 单元、浏览器)、不碰 P4(浏览器 完全对齐)、不碰 P6(privsep worker)。分支 feat-chv-muse-p5 (从 feat-chv-cover100 分出,基线 HEAD 06c3e17)。

0. 起点(P3 已做的,本轨不重写)

P3 交付的 cloud/chv/sentinel.py(决策层,纯函数 + 内存态队列, 标准库):SentinelPolicy.evaluate()(allow/deny/ask;L4 解析后 IP/端口/协议 + L7 主机/方法/路径;SSRF 挡截;未知连接器/scheme/ 端口/路径越界 → deny;不在白名单 → ask);严格能力 Capability (绑定 {连接器, 主机, 方法, 路径, 有效期, 次数},默认单次 + 300 秒 TTL,matches()/use());ApprovalQueue(ask 记入内存态待审批, resolve 只标记不放行)。两个接线点:wake 时 Gitea 出口预审、 authd 放凭证前评估。P3 明确列为后续的本轨三项:eBPF 污点传播、 审批 UI 不在对话内(只留队列)、能力只有一次性一档(官方有五档)。

1. 现状 vs Muse

项 现状(实测/代码为准) Muse 目标 本轨做法
污点出口 无。Sentinel 是决策层,不拦截客内流量;客内直连靠 Tinyproxy 白名单 + 宿主防火墙兜底;进程“读了用户数据”这个事实没有任何地方记录 每个工具执行进程初始干净,读用户数据后变污点;干净 + 窄范围自动放行策略 + 出站 URL 检查通过 → 免打扰放行;污点或不可验证进程失去自动放行、回正常审批流;eBPF cgroup 程序做网络拦截与进程归因、LSM hook 做污点传播 cloud/chv/taint.py(污点追踪器:进程干净/污点两态、读用户数据事件 → 污点、子进程继承、审计)+ cloud/chv/ebpf_taint.py(eBPF 程序源码 + 加载器 + 能力探测 + 降级);宿主侧先做可测试的最小闭环:策略引擎(纯标准库、可单测)+ eBPF 加载层(可探测、失败时明确降级、不冒充已加载)。客内 eBPF 加载可行性实测后写进 §3,不行就写清阻塞点
严格能力分级 只有一档:单次 + 300 秒 TTL(P3 默认)。无会话/任务/时限/永久的概念;无“用例”维度(只绑连接器/主机/方法/路径) 严格能力绑定到特定连接器/目的地与用例,支持一次性、会话级、任务级、时限级、永久级授权;Sentinel 决定向用户呈现哪几种授权类型;后续调用与授权范围精确匹配 cloud/chv/capabilities.py:五档全实现(one-shot / session / task / timed / permanent),能力绑定 {连接器, 目的地, 用例} 三元组 + 方法/路径/次数/过期;matches() 精确匹配检查(超范围即 deny + 审计);每档的签发条件与上限写进规则表(永久级默认不签发,须显式策略开启 + 审计)
审批 UI 在对话外 只有 ApprovalQueue 内存态队列:ask 记入、resolve 只标记;没有任何请求/答复通道;对话内容伪造审批的风险只在文档里写了约束,无机制防 Sentinel 直接向客户端发审批请求,弹窗在客户端 UI 内,答复直接回 Sentinel;目的:防对话内容伪造审批 cloud/chv/approval_channel.py:独立审批通道(请求/答复协议、nonce + 有效期 + 签名/HMAC 校验,答复须与请求绑定;对话内容里出现的“批准”字样一律无效);通道两端接口 + 契约文档;客户端 UI 呈现是另一侧的事,留好接口、不冒充已做 UI
默认策略 只有 default-deny + 白名单/拒绝名单 + L7 规则;无“只读/已允许/低风险不打扰”的分层规则,无可调谨慎度 只读、先前已允许、明显低风险动作可不打扰通过;用户可把默认调得更谨慎或更宽松 cloud/chv/policy.py:默认策略规则表(只读方法 GET/HEAD + 已允许主机/路径 + 低风险判定)+ 谨慎度三档(default / cautious / permissive,默认 default;permissive 不放行写操作与敏感路径);规则变化(档位切换、规则增删)全部审计
审计 P3 的 _emit 契约:sentinel_egress_allow/deny/ask,detail 只含连接器/主机/路径/verdict/原因,不含凭证值 审计轨迹展示已做与计划做的事 沿用契约,新增事件:sentinel_taint_marked(进程变污点)、sentinel_auto_allow(干净进程自动放行)、sentinel_capability_denied(超范围/过期/超次)、sentinel_approval_requested/answered(通道审批)、sentinel_policy_changed(规则/档位变化);detail 只含进程/连接器/目标/ verdict/原因,绝不含用户数据内容与凭证值

2. 改了什么(本轨交付物,已做完)

  • cloud/chv/taint.py(新,标准库):污点追踪器——进程注册(pid/cgroup/连接器/用例)、干净 → 污点(mark_tainted(pid, source),source 只存分类)、子进程继承污点、污点不可清除(无任何清除入口,只随进程退出消失)、is_tainted、auto_allow_eligible(污点与未知 pid 一律 False)、审计(事件名 + pid + 原因,无内容、无凭证值)。
  • cloud/chv/ebpf_taint.py(新,标准库):eBPF 程序源码常量(cgroup_skb/egress 拦截 + taint_map HASH 进程归因 map + RINGBUF 事件上报;lsm/file_open 污点传播骨架,共用 pin 住的 map,路径表由用户态下发、不读文件内容)+ EbpfTaintLoader(能力探测:内核版本、/sys/fs/bpf 是否存在可写、CapEff bit 39 CAP_BPF / bit 21 CAP_SYS_ADMIN、bpftool/clang/llvm-objdump;状态 loaded/degraded/blocked + 原因;加载失败一律降级为 policy_engine_proxy_hooks,try_load 须 bpftool 加载 + pin 在位双重确认才报 loaded)。
  • cloud/chv/capabilities.py(新,标准库):五档严格能力,继承 P3 Capability——one-shot(单次/300 秒)、session(会话 id 绑定,默认 3600 秒)、task(任务 id 绑定,默认 3600 秒)、timed(须显式 ttl)、permanent(默认拒绝,须显式 allow_permanent=True);绑定 {连接器, 主机, 用例} 三元组 + 方法/路径/次数/过期;matches(request, now, scope) 精确匹配(scope 须按关键字传,now 仍占第二位置参数,与 P3 旧口径一致);use()/revoke();签发/使用/过期/超次/撤销全审计。
  • cloud/chv/policy.py(新,标准库):默认策略规则表 + 谨慎度三档(default:已允许主机 + 路径前缀;cautious:精确主机 + 精确路径;permissive:只读 + 非敏感即候选,不必先前已允许);三档共性:写操作与敏感路径(/admin、/settings、/login、token 相关)永远不自动放行,污点进程一律不自动放行;set_caution/add_rule/remove_rule 每次变化记 sentinel_policy_changed 审计。
  • cloud/chv/approval_channel.py(新,标准库):独立审批通道——ApprovalRequest.payload()(pending_id + nonce + 目标描述 + 原因 + 过期,默认 15 分钟,无凭证值与用户数据内容);Answer(pending_id + nonce + verdict + 过期 + HMAC-SHA256 签名);verify_answer(pending 存在 + nonce 对上 + 未过期 + 签名对上 + verdict 合法,五项缺一即 False);resolve_via_channel(校验通过才调 ApprovalQueue.resolve,成功即消费登记、答复只能用一次);密钥由调用方保管,通道不保存密钥、不进载荷、不进日志。
  • 接线(cloud/chv/sentinel.py,唯一改动的已有文件):evaluate() 新增可选接线参数(taint_tracker/pid/default_policy/tier/scope),不传时行为与 P3 完全一致;安全检查(步骤 1–6)抽成 _safety_verdict;新增自动放行步骤(干净进程 + 只读 + 已允许 + 低风险 + 过 L7 路径规则 → allow + 按档位签发能力,原因 policy_auto_allow;污点进程一律不放行、回到正常审批流);档位签发失败回落单次(更严格,原因 capability_tier_fallback,不抛错);Decision 加 tainted 标记(审计里仅当 True 时出现);Capability 基类的 max_uses/uses_left/expires_at 放宽为 Optional(None = 不限,供五档用;单次档仍是 int,行为不变)。
  • cloud/tests/test_chv_muse_p5_taint.py(18 项)、test_chv_muse_p5_capabilities.py(21 项)、test_chv_muse_p5_approval.py(11 项)、test_chv_muse_p5_wiring.py(11 项,接线:自动放行/污点回流/三档策略/档位签发与回落/通道端到端/对话伪造无效)。新测试共 61 项。

3. 诚实边界(本轮不宣称的东西)

  1. eBPF 加载在本机实测不行,证据确凿(不是推断):本 Muse VM 实测(2026-11-07,ctypes 直接调 bpf(),syscall 号 321):最小合法程序 BPF_PROG_LOAD(SOCKET_FILTER,r0=0; exit,GPL)返回 -1,errno 1 EPERM,verifier 日志为空;BPF_MAP_CREATE 同样 -1 EPERM。空 verifier 日志说明在 verifier 之前就被挡;/proc/self/status 显示 Seccomp: 2(filter 模式)——bpf() 系统调用本身被 seccomp 挡,能力位在位不等于系统调用放行。其余探测:内核 7.0.0-43-generic;CapEff 000001fffff7cfff 解码 CAP_BPF bit 39 = 在位、CAP_SYS_ADMIN bit 21 = 在位;/usr/include/linux/bpf.h 在位,gcc 在位;但无 /sys/fs/bpf(/sys/fs 下 0 处 bpf 挂载)、无 bpftool/clang/llvm-objdump。加载器 probe() 因此报 blocked(blockers 含 bpffs_missing、tool_missing:bpftool/clang/llvm-objdump)。本轨交付“策略引擎 + 加载器 + 降级”与本实测结论,不把“写了 eBPF 程序源码”等同于“eBPF 已在拦截流量”。客内(WSL 测试机 VM 里)加载可行性须真机验证,见 §4;教训:真机验证须先确认客内容器/VM 的 seccomp 配置是否放行 bpf(),只看 CapEff 会误判。
  2. 污点追踪的“读用户数据”事件靠调用方上报:纯用户态追踪器不知道进程真读了什么文件——污点标记的输入是工具执行层在读用户数据前调用 mark_tainted()(或 LSM hook 回调,eBPF 通了才有真事件)。没接 LSM hook 之前,漏报是可能的;本轨不宣称“所有读用户数据的行为都被捕获”。
  3. 审批通道不是客户端 UI:本轨做请求/答复协议与校验,不做弹窗 UI。没有客户端接入之前,ask 仍须人工在通道外处理;不得写成“审批弹窗已上线”。
  4. 永久级能力默认不签发:按 Muse 口径 Sentinel 决定呈现哪几种授权类型;本轨永久级默认关闭,须显式策略开启 + 审计;开启后仍绑定三元组与审计,永不过期不等于无审计。
  5. 无真机验证:本轮全部是代码 + 本地单测。真机待验证清单见 §4,测试机须排队(第三棒 V-1~V-9 与 round-11 之后)。

4. 真机待验证清单(测试机空闲后,round-11 之后排队)

  1. eBPF 程序在 WSL 测试机客内真加载:加载是否成功、cgroup 拦截是否真拦住直连、进程归因 map 是否对得上 pid、LSM hook 是否真收到读事件。
  2. 污点进程在真机上的出口表现:干净进程自动放行、读用户数据后出口回审批流、ask 停止执行。
  3. 五档能力在真机 wake/同步路径下的表现:会话/任务级能力跨多次调用仍有效、过期/超次即拒。
  4. 审批通道端到端:ask 发出 → 通道外答复 → 放行/拒绝生效;对话内容伪造答复在真机上无效。
  5. 默认策略三档在真机上的表现:cautious 档是否多拦、permissive 档是否仍挡写操作与敏感路径。