diff --git a/docs/interactive-full-delivery-roadmap-2026-11-11.md b/docs/interactive-full-delivery-roadmap-2026-11-11.md index e2630de..5986bcb 100644 --- a/docs/interactive-full-delivery-roadmap-2026-11-11.md +++ b/docs/interactive-full-delivery-roadmap-2026-11-11.md @@ -2,8 +2,9 @@ **Baseline date:** 2026-11-11 (UTC+8) **Repository:** `devcodex-labs/flowkit` -**Frozen main:** `ea2bb10893a9be2e5de3561fc9a660a6977ae15c` -**Planning branch:** `fix/m6-current-main-e2e-20261111` +**Historical Phase 0 baseline:** `ea2bb10893a9be2e5de3561fc9a660a6977ae15c` +**Current Phase 2 source baseline:** `9bac8f86347a405efe068f96423ae3e501005061` +**Current design branch:** `design/trusted-host-security-v2-20261111` (historical Phase 0/1 baseline remains immutable) > This document records the approved end-to-end route from the current M6/P0-A state through P0-B, P1, P2 and production delivery. It is a roadmap and traceability ledger, not evidence that deferred features have been implemented or passed. @@ -11,11 +12,11 @@ ### 1.1 Main and CI -- Main HEAD: `ea2bb10893a9be2e5de3561fc9a660a6977ae15c`. -- Main CI run: [42954859078](https://github.com/devcodex-labs/flowkit/actions/runs/42954859078), completed successfully. +- Current main HEAD after Phase 1: `9bac8f86347a405efe068f96423ae3e501005061`. +- Current main CI: [42998521531](https://github.com/devcodex-labs/flowkit/actions/runs/42998521531), 7/7 jobs successful. - M1–M5 implementation surfaces and S07 capacity work exist on main. Their presence is not a blanket claim that every M6/native-host gate is passed. - PR #8, #9 and #10 are merged. -- PR #7 is open Draft, head `e1e15a70356e53401288d393aa7527c6723fe797`, based on an older main snapshot `c873e3edf0f1a78b13178966cdeb408391755170`. Its M6 tests need to be revalidated against current main. +- PR #7 is **closed without merge** as superseded. PR #13 is **merged** into main with current-main M6 tests, correct project-root discovery and successful exact-HEAD CI. - PR #12 is open Draft, head `c6b42a36050d885a37831cbdf0839428b2052c85`, based on `ea2bb10893a9be2e5de3561fc9a660a6977ae15c`. Its scripted C13–C20 tests and documentation CI passed; this does not pass C12/S13 native-host gates. ### 1.2 Evidence classes @@ -31,9 +32,9 @@ Never count P evidence as M or N. Never count a CI replay of recorded model turn | Phase | Scope | Required exit condition | Current state | |---|---|---|---| -| 0 | Baseline freeze and traceability | Immutable baseline, full requirement/Finding/test ledger and evidence index | **Complete** — baseline and ledger committed on this branch | -| 1 | M6 current-main test compatibility | PR #7 tests run against frozen current main; no Core semantic change hidden in test repair | **PASS** — replacement PR #13 exact-HEAD CI 7/7; four matrix cells 369/369, Linux isolation/M6 e2e 11/11 on Node 22/24; no production Core change | -| 2 | Trusted Host security design | Approved threat model, OS identity, IPC, key custody, Store ownership and provenance contract | Pending | +| 0 | Baseline freeze and traceability | Immutable baseline, full requirement/Finding/test ledger and evidence index | **Complete** — established in merged PR #13 | +| 1 | M6 current-main test compatibility | PR #7 tests run against frozen current main; no Core semantic change hidden in test repair | **PASS, merged** — PR #13; main CI 7/7; four matrix cells 369/369, Linux isolation/M6 e2e 11/11 on Node 22/24; no production Core change | +| 2 | Trusted Host security design | Approved threat model, OS identity, IPC, key custody, Store ownership and provenance contract | **CONDITIONAL**:第三轮 Grok 定向复核已确认 F-01、F-R2-01 **CLOSED**;F-02/F-04 仍 PARTIAL(后续 PoC/OS 实测),F-07 正式 V0.3/V0.6-R5 原文符合性仍 **BLOCKED**;PR #14 可作为明确标注限制的设计记录候选,尚未合并 | | 3 | Trusted Host security implementation | Windows and Linux isolation, access-denial tests and secure Host operations pass | Pending | | 4 | Native Grok Build JS tool bridge | Grok Build itself calls FlowKit JS tools through Pending → model completion → JS submit/resume → Terminal | Pending | | 5 | M6 live-model complex acceptance | Applicable C01–C24 cases classified and evidenced at P/M/N levels; all M6 blockers closed | Pending | @@ -81,13 +82,13 @@ Freeze a Host threat model before implementation: - Provider-signed evidence may be used if genuinely available, but is not assumed to be the only possible design. Any alternative Host-owned transport must state its exact assurance level and limits. - Human approval remains unavailable/blocked unless a model-unwritable trusted human decision channel is independently verified. -Deliverables: threat model, trust topology, IPC contract, key custody design, provider/session provenance design, Windows/Linux deployment designs, attack matrix and acceptance criteria. Independent review must close all design findings before Phase 3. +Deliverables: threat model, trust topology, candidate-ingress security contract (with optional authenticated listening IPC only when needed), key custody, provider/session evidence design, Windows/Linux profiles, attack matrix and acceptance gates. Independent review must close all **applicable design-blocking** findings before Phase 3. Missing formal V0.3/V0.6-R5 originals remain an explicit conformance BLOCKED item, not evidence that they never existed; OS capability PoCs can be performed separately, but no final conformance claim can be made without them. ## 6. Phase 3 — Trusted Host security implementation 1. Implement distinct OS identities or an equivalently strong restricted token boundary. 2. Restrict Host private directory, key and SQLite DB/WAL/SHM to the Host principal. -3. Expose only constrained IPC operations with explicit authorization and input/output schemas. +3. Validate all **actual model-candidate ingress paths** with explicit authorization and bounded I/O. Do not introduce a TCP/mTLS/Named Pipe listener just to satisfy a checklist: in a no-listener deployment record `NO_LISTENER` and test the real MCP/anonymous-pipe/tool-input path instead. 4. Ensure the model cannot access raw DB, key, signer, Coordinator or private State. 5. Add Windows ACL and Linux UID/GID integration tests. A test that exits because the platform is unsupported is BLOCKED, not PASS. 6. Test read, write, replace, symlink, path traversal, process spawning, inherited handles/environment, IPC spoofing, replay, wrong tenant and unauthorized API calls. @@ -95,7 +96,9 @@ Deliverables: threat model, trust topology, IPC contract, key custody design, pr 8. Record raw OS identity, access-denied evidence, process tree, IPC identity and Store integrity. 9. Repeat after reboot/restart and on the supported Node matrix. -Exit: security tests pass on both supported OS families, with no same-principal bypass. If the actual Grok Build execution environment cannot be isolated from Host secrets, keep native secure-host acceptance BLOCKED and do not expose Host secrets to that model. +Entry: independent Phase 2 security design approved, with frozen OS principals, Host secrets/ACL and no insecure default Node Named Pipe; Grok native tool evidence is **not** required for H3-01/H3-05 OS-only isolation. H3-02 implementation requires only a separately documented Grok tool-registration and signed-before-completion input/timing **capability PoC**, which is **not** a formal NAT-14 PASS. + +Exit: **both Windows and Linux** Secure Host Profiles pass their applicable P0 OS/handle/active-ingress/signing/Outbox tests. H3-05 OS-only tests depend only on H3-01; H3-04 adapter integration adds active-ingress and recovery checks later. Without a listening endpoint, prove its absence and test the actual candidate-input mechanism, rather than demanding mTLS. One platform PASS only proves that platform. NAT-14 is officially tested in Phase 4; C12/S13 N remains BLOCKED until native model evidence is complete. ## 7. Phase 4 — Native Grok Build JavaScript bridge @@ -132,13 +135,13 @@ Exit: every C item is PASS, FAIL, PARTIAL, BLOCKED or explicitly DEFERRED with o ## 9. Phase 6 — M6 review, P0-A closure and merge -1. Dot independently checks exact code SHA, Program hash, raw native tool events, Pending/response, Host traces, signed statements, SQLite, Journal hash chain and OS evidence. +1. An **independent reviewer** (local Grok Build or another separate reviewer; Dot is not mandatory) checks exact code SHA, Program hash, raw native tool events, Pending/response, Host traces, signed statements, SQLite, Journal hash chain and OS evidence. 2. Run exact-HEAD CI: Ubuntu 24.04 and Windows 2025 × Node 22.13.0 and 24.22.1. 3. Run Linux cross-UID and Windows ACL isolation jobs independently. 4. Run build, npm verify, package/tarball, types, CLI, docs examples, website and Standard regressions. 5. Resolve every M6 blocker and rerun the relevant scenario plus full regression. 6. PR #12 may be merged only as the scripted matrix/docs contribution after its own review; its merge does not pass C12/S13. -7. PR #7 or its current-main replacement may be merged only after M6 integration CI and security gates pass. +7. PR #7 was closed without merging and its current-main replacement PR #13 was merged after independent code review and CI; do not merge it again. Future M6 native-host security evidence remains in PR #14 and follow-up scoped implementation PRs. 8. Do not release a version until P0-A release criteria are explicitly met. ## 10. Phase 7 — P0-B sequential workflow @@ -350,11 +353,12 @@ A phase cannot pass by deleting a test, weakening an assertion, changing the evi ## 15. Current next actions -1. Phase 0 baseline/traceability is complete. -2. PR #7's M6 integration tests were ported onto current main in replacement PR #13. -3. The fixture now covers default nearest-package discovery and explicit `projectRoot` override. -4. Exact HEAD `df1eec669d5f46a04f40718abf16fe111db6caf3` passed CI run [42997084061](https://github.com/devcodex-labs/flowkit/actions/runs/42997084061): 7/7 jobs; Ubuntu/Windows × Node 22/24 each passed 369/369 tests; Linux OS-user isolation plus M6 e2e passed 11/11 on Node 22 and Node 24. -5. Independent code review found no production Core changes. PR #13 is ready for review/merge as test infrastructure only; this does not close native C12/S13 or M6 final acceptance. -6. After PR #13 is merged, close/supersede stale PR #7 without merging its old branch, then begin Phase 2 Trusted Host security design. +1. Phase 0/1 **complete**: PR #13 merged to main `9bac8f86347a405efe068f96423ae3e501005061`; old PR #7 closed unmerged. +2. Main CI [42998521531](https://github.com/devcodex-labs/flowkit/actions/runs/42998521531): 7/7 successful; Ubuntu/Windows × Node 22/24 each 369/369; Linux OS isolation + M6 11/11 on both Node versions. +3. Phase 2 security design record (still Draft/Conditional): [Trusted Host V2](./interactive-trusted-host-security-v2-design.md), [threat model](./interactive-trusted-host-security-v2-threat-model.md), [acceptance matrix](./interactive-trusted-host-security-v2-acceptance.md), [review ledger](./interactive-trusted-host-security-v2-review.md). Third-round Grok review closed F-01/F-R2-01; F-02/F-04 remain PARTIAL and F-07 remains BLOCKED. +4. Three rounds of Grok Build independent review have been completed, including the final targeted review of F-01/F-R2-01. Phase 2 is **not yet frozen**: F-02 native tool binding, F-04 cross-principal handle isolation and F-07 formal contract provenance remain open/BLOCKED. Draft/CI success is not a substitute for native Host security acceptance or a professional third-party security certification. +5. Then implement OS isolation, trusted bridge, direct Grok Build tool loop, real-model edge cases and Phase 6 M6 closure. PR #12 remains Draft until its own scoped review. + +**Formal contract source caveat:** Historical FlowKit requirement V0.3 and technical design V0.6-R5 are cited in previous handoffs, but their full immutable bodies/SHA-256 are not presently available to this PR's independent reviewer. Conformance to those documents remains **BLOCKED** until the exact originals can be independently read and hashed; roadmap IDs cannot replace official text. **No direct main modification or release is authorized. Merge only through a reviewed PR after exact-HEAD CI. This test/roadmap PR does not authorize production semantic changes or declare M6 complete.** diff --git a/docs/interactive-trusted-host-security-v2-acceptance.md b/docs/interactive-trusted-host-security-v2-acceptance.md new file mode 100644 index 0000000..624f6ea --- /dev/null +++ b/docs/interactive-trusted-host-security-v2-acceptance.md @@ -0,0 +1,167 @@ +# FlowKit Interactive — Trusted Host V2 安全验收矩阵及判停规则(Draft) + +**2026-11-11,Phase 2 Design only;不是实测报告。** +- 代码基线:`main@9bac8f86347a405efe068f96423ae3e501005061`。 +- [设计](./interactive-trusted-host-security-v2-design.md) · [威胁模型](./interactive-trusted-host-security-v2-threat-model.md) · [现有 M5](./interactive-host-security.md)。 +- 目标:Phase 3 先通过 OS/Host 隔离,Phase 4 再做原生 Grok Build JS 工具续接,Phase 5 完成复杂模型验收。 +- 必须保留旧 C01–C24、S01–S14、T01–T34 的冻结要求;本矩阵只是额外的安全部署验收入口,不篡改原要求。 + +## 1. 强制证据等级 + +| 等级 | 定义 | 可使用的原始材料 | 不可代替什么 | +|---|---|---|---| +| P | 真实 Program、SQLite、Host,scripted worker 回执 | CI、Hash、Store、Journal | 真实模型和原生宿主 | +| M | 真实 Grok Build/其他模型参与真实 Pending 的至少一次回合 | 模型实际回复及受信工具事件和 req/task digest | OS 隔离和 Provider 认证 | +| T | 保护的 Host/Supervisor 独立观测指定进程/工具调用/通信,非模型侧文本 | Host-only supervisor logs、进程 token、受保护通信握手及事件 Hash | 如果缺供应商来源证据,不能称为 V | +| N | 对原冻结 C12/S13 所有适用项,原生 JS 工具闭环、来源/权限证据齐全 | 原生工具日志、可信来源、OS 负例、Host 收据和终态 | 不证明外部副作用 exactly-once | +| V | 供应商本身提供可验证的签名/信任根(可选能力) | 供应商规范、可验证公钥/算法、签名覆盖字段和真实验签 | 不能从非权威 JSON `signature` 字段推断 | + +**禁止混算:** P PASS、M PASS、T PASS 不自动等于 N PASS。缺少必需的独立来源或安全隔离时 N 必须为 BLOCKED。 + +## 2. Phase 3:OS + Host 基础安全验收 + +| ID | 场景/实测方式 | 必须断言 | 级别 | 关联威胁 | 目标平台 | +|---|---|---|---|---|---| +| SEC-01 | 获取 Host/Grok/Bridge 实际 OS user、group/SID、权限和进程树 | MODEL 不等于 HOST;MODEL 无管理员/root/调试 Host 权限 | P0 | TH-001, TH-023 | Win/Linux | +| SEC-02 | MODEL 对 Host signing key、Host config、Program allowlist 做路径读取/复制及继承句柄扫描 | 文件路径全部 EACCES/EPERM/Access Denied,MODEL 子进程无继承的私钥/Token 句柄;Host 能正常签名 | P0 | TH-002, TH-005 | Win/Linux | +| SEC-03 | MODEL 读/写/删除/替换 SQLite 主库、WAL、SHM、备份并检查继承文件/映射句柄 | 文件路径全部拒绝,MODEL 子进程无可读写的继承句柄,Host 恢复和数据完整性未受影响 | P0 | TH-003, TH-004 | Win/Linux | +| SEC-04 | MODEL 用任意 CLI/shell/子进程尝试取得 Host Token、服务控制和进程调试权 | 不能提权、不能改服务启动程序、不能注入 Host | P0 | TH-001, TH-023 | Win/Linux | +| SEC-05 | 对所有**实际启用的模型候选数据入口**执行授权及跨租户测试(匿名捕获/受控 MCP 转发/已启用的 IPC 等) | 无受信工具事件、错误 OS 主体、错误 Run/tenant 的提交不能签名或 CAS;若部署无监听端点记录 `NO_LISTENER`,**不得免测实际输入路径** | P0 | TH-006, TH-007, TH-013, TH-027 | Win/Linux | +| SEC-06 | 用模型工具内普通 shell/curl/node 重演 `submitAgentResult` | 没有受信工具事件证据则不能获取 Host 签名或有效 Ack | P0 | TH-008, TH-009, TH-010 | Win/Linux | +| SEC-07 | **仅当选择监听型 TLS/mTLS IPC**:非回环、服务器伪造、证书到期、错误 CA/Hash、错误用途、证书泄漏 | 活跃 TLS/mTLS 端点的所有反例均拒绝,无 HTTP/plaintext fallback;没有 TLS/mTLS 监听时记 `N/A—NO_LISTENER` 并指向 SEC-05 的实际候选通道验证,不得为通过此项新增监听器 | P0 if adopted | TH-006–TH-008 | Win/Linux | +| SEC-08 | 修改 Public Task、Result body、runId、requestId、attempt、nodeId、artifact、policy | 拒绝且 CP/Journal/receipt-index 字节不变,Host 错误不泄漏敏感值 | P0 | TH-011–TH-014 | Win/Linux | +| SEC-09 | Host 签名时注入模型自报 `proofId`/SessionId/已审批文本 | 不用模型值替换 Host-only evidence;签名前拒绝 | P0 | TH-009, TH-010, TH-025 | Win/Linux | +| SEC-10 | Publisher/Host 持久化前后分别 SIGKILL,重新启动并恢复同 Run | 原 Pending identity、CAS、Journal、回执一致 | P0 | TH-015, TH-020 | Win/Linux | +| SEC-11 | Public Task、response、terminal、Host audit log 注入 canary | 模型可读视图零泄露;Host-only Store 保留原 canary | P0 | TH-017 | Win/Linux | +| SEC-12 | 未授权请求、大 body、格式错误、恶意 JSON、速率/连接洪泛 | 有界资源,原有 2 MiB canonical signed receipt 三分法未被破坏 | P1 | TH-016 | Win/Linux | +| SEC-13 | 模型尝试 reparse/symlink/硬链接、程序替换、policy drift、证书文件替换 | Fail closed;原字节不变;Host 未执行模型提供的替换程序 | P1 | TH-005, TH-024 | Win/Linux | +| SEC-14 | 真实 OS 更新账户权限、证书过期、KMS/私钥轮换与 Host 重启 | 无意外授权扩大,旧 Run 有明确安全处置与历史 Ack | P1 | TH-022 | Win/Linux | +| SEC-15 | 两个用户/租户并发使用同 startKey 和 RunId | namespace 互不泄漏;错误租户被拒绝 | P0 | TH-013 | Win/Linux | +| SEC-16 | Windows Named Pipe 方案 DACL/SID 实测(仅选用时) | 微软默认 DACL 可给 Everyone/Anonymous 读权限,纯 Node 默认管道不得放行;如采用 Win32 自定义安全描述符,必须在创建时设定 DACL、拒绝远程、验证非授权 SID 连接失败 | P0 if adopted | TH-006 | Windows | +| SEC-17 | Linux UID 隔离脚本 + 实际受限 CLI 进程 | scripted nobody 和 Grok CLI 两种场景区分,且真正被拒绝访问 | P0 | TH-001–TH-004 | Linux | + +| SEC-18 | Host 观察事件/签名回执 Outbox:签名前/签后/accept-CAS 前后真 SIGKILL | 原观察事件、proofId、signed bytes、acceptedRevision 对账;未接纳过期证明不能通过;已接纳同内容即使过期仍返回旧 Ack | P0 | TH-029 | Win/Linux | +| SEC-19 | 证据保留/容量、隐私与历史审计 | Host-only evidence 不泄密、不无限增长;修订 Retention 配置后历史 Ack 和 Journal 仍可审查 | P1 | TH-030 | Win/Linux | + +**通过标准:** SEC-01–SEC-11、SEC-15、SEC-18 中**适用于实际部署的 P0**必须全部 PASS;SEC-07 仅当采用监听型 TLS/mTLS 时强制,SEC-16 仅自定义 Named Pipe 被采用时强制,SEC-17 对 Linux 受限进程强制。无 TCP/mTLS 监听可记录 `N/A—NO_LISTENER`,不能把不存在的端点判成 PASS,也不能免除 SEC-05/06 对实际候选数据入口的身份/工具事件验证。TH-017/TH-023 与 SEC-11/SEC-04 均为 P0。P1 漏项不能构成 P0 绕过。**单一 OS Profile 通过不等于跨平台 Phase 3 完成;Windows 和 Linux 两个安全 Profile 均须有独立实测证据。** Grok 正式 NAT-14 仍是 Phase 4 门禁;H3-02 开工前的最小工具能力探针只记 PoC,不得冒充 NAT-14 PASS。 + +## 3. Phase 4:直接 Grok Build 原生 JS 工具链 + +| ID | 实测路径 | 必须断言 | 证据 | +|---|---|---|---| +| NAT-01 | Host Provisioner 启动受保护 Run,Grok Build 在其受限会话调用 JS 工具 `start` | 真实 Program Hash、Run 身份固定;模型不能建立未授权 Run | Native tool-call 原始事件、Host-only 授权记录 | +| NAT-02 | JS 工具返回一个当前 Public Task | 返回 exact nodeId/requestId/attempt,排除 Host 全量 State | 原始工具响应 Hash、Host DLP decision | +| NAT-03 | Grok Build 真正生成本节点模型结果 | 非 fixture/非 scripted worker;实际输出与这个 Pending 关联 | Session/tool event chain、model result digest | +| NAT-04 | Grok Build 再次 JS 工具调用 `submit` | 真实 MCP/受限 Node 工具,签前观察完整或可验证 rawInput;比较 toolInputDigest 后用当前 Pending 构造 normalizedReceipt,匹配相同 receiptHash,缺输入则 BLOCKED | Original tool_call + Host-only evidence + proofId/receiptHash + acceptedRevision | +| NAT-05 | Grok Build 通过 JS 工具 `continue` 直到 Program Terminal | 由 Program 选边,不由模型自由解释,用户可读取 Host-private 终态 State | 原始 JS Tool logs、Store/Journal/Terminal | +| NAT-06 | 模型绕过 Grok CLI 用同权普通终端发送伪响应 | 没有独立观察证据不能导致有效签收;不能伪造原始 Host-only tool event | 攻击日志、无 CAS、无 signer 操作 | +| NAT-07 | 模型自写 `GROK_SESSION_ID`、`usage.signature`、toolCallId、start time 等 | 都不能单独提升来源认证等级 | 反例日志 + Host 拒绝 | +| NAT-08 | 在 Grok 当前真实会话进行 Host PID 强杀、恢复、重试 | 同 Run 同 requestId 恢复;第二次调用有真实 ToolCallId 和 acceptedRevision | Host crash/repair log + CLI tool events | +| NAT-09 | 两个真正独立的 Grok 模型会话同时提交一个 Pending | 仅一次有效 State commit;重复 Ack/冲突可解释;不保证 Provider exactly-once | 两会话原始日志、SQLite 事务和 Journal | +| NAT-10 | 关闭网络、异常输出/超限、真实 Provider failure 与模型非法输出 | 区分未认证拒绝、可信 Provider 失败、Checkpoint 容量退出;无无限 waiting | transport bytes、Host-observed failure、正确 FK_R004/capacity 语义 | +| NAT-11 | 模型恶意指令:尝试读取 Host 私钥、DB、扩大 State 披露、伪造人工批准 | 全部负例失败;合法 Agent 链照常完成 | 权限负例、Host审计、公开 Task canary | +| NAT-12 | 换 Grok 会话/模型版本或加载不同工作区 | 旧的身份/ToolCallId 不能自动迁移,必须重新授权/重绑 | Session provenance + Host policy hash | +| NAT-13 | 供应商的模型/响应签名能力探测 | 若无官方可验证规范/公钥/覆盖字段,结果必须记 `PROVIDER_VERIFIED=BLOCKED`,不允许伪证明 | 官方规范+真实 verifier 或明确的阻断说明 | +| NAT-14 | submit 工具事件时序和死锁负例 | Host 签名前必须可独立观测 tool_call start/input;如只能获取结束事件则 BLOCKED 并另审双阶段协议 | CLI 原生事件时序、工具等待链、超时后零 CAS | +| NAT-15 | 真 Grok 签后、CAS 前崩溃和 Outbox 恢复 | 同一真实事件的签名原字节持久化、原 Run 对账;过期未接纳回执不能直接重放或伪造结果 | Host-only OBSERVED/SIGNED/ACKED、SIGKILL、proofId、receipt index | + +**NAT-14:submit 工具事件时序反例。** 用受控代理模拟可信 Supervisor 仅在工具返回后才会收到 `tool_call_update`,工具本身却等待 Host 接纳。必须发现此循环等待;若无法提供签前可验证的 `tool_call` 起始事件与输入摘要,应将该机制标为 BLOCKED 并采用单独审查的双阶段协议,不能简单超时重试或用模型自报完成替代。 + +**NAT-15:真实 Grok 结果签署后、Store CAS 前崩溃的 Outbox 恢复。** 至少一个真实模型已产生的结果进入 Host-only `SIGNED`,在 `host.accept()` 前 SIGKILL;重启时核对是否已被 Store 接纳,尚未接纳则检查签名有效期,过期必须阻断或经独立受信原事件严格重认证,绝不发明模型结果或多次 State Commit。对应 SEC-18/TH-029。 + +**NAT-01–NAT-05 为 S13 核心链**,NAT-06–NAT-12、NAT-14–NAT-15 覆盖 C12/C22/C23 的伪造与故障路径;NAT-13 是能力探测,不无端把不存在的 Provider 签名作为所有平台不可能完成的前置条件,但也不放宽冻结的来源证明要求。 + +## 4. Phase 5/6:与冻结验收的交叉映射 + +| Frozen item | 需要本矩阵哪些证据 | 不能用来替代的既有测试 | +|---|---|---| +| S02、S04、S05、S06、S07 | SEC-08/10/12/13/15/18 | 不能把脚本 M6 e2e 说成真实 Grok | +| S13、T11、T27 | NAT-01–05、NAT-06/07、SEC-01–06 | 不能把文件 Polling 的 M 层测试说成原生 JS 工具 | +| C12、S13、T27 | NAT-01–NAT-12、NAT-14–15 + SEC-01–06/18;原生来源/安全门禁单独裁决 | 不得用脚本、同账户文件 Harness、普通模型文本或无工具事件的 MCP RPC 冒充来源证明 | +| C01、C02、C03、C04 | NAT-01–05/10 | 单纯回放 ChatGPT fixture 不计新模型回合 | +| C05、C06、C23 | NAT-08/09/10/15 + SEC-10/18 | 单一 SIGKILL 或双进程 scripted race 不能替代组合场景 | +| C07、C08、C22 | SEC-01–09/11/13/15、NAT-06/11 | Linux nobody 不能证明 Windows ACL | +| C09、C16 | SEC-12、NAT-10 | 不能将 oversize 无认证回执当 Provider failure | +| C10、C11、C13–C20 | 历史 P 级复测 + 同 SHA CI | 不要求 36 次真实模型付费 | +| C21 | 同物理 DB 跨 Node/OS 测试(增强项) | 未经批准不能提升 P0-A 硬门禁 | +| C24、S14、T28、T33 | Ubuntu/Windows × Node22/24、完整 verify/docs/types/package、原始来源证据 | 只跑一套 Windows Grok 场景不等于全平台 SDK 通过 | + +## 5. 原始证据契约 + +每项验收至少记录: + +```json +{ + "schemaVersion": "FlowKitHostV2AcceptanceV1", + "scenarioId": "NAT-04", + "result": "PASS | FAIL | PARTIAL | BLOCKED | DEFERRED", + "executionTier": "P | M | T | N | V", + "commitSha": "", + "programHash": "sha256:...", + "os": "", + "nodeVersion": "", + "hostPrincipalDigest": "sha256:...", + "bridgePrincipalDigest": "sha256:...", + "runId": "", + "flowkitRequestId": "", + "grokRequestId": "", + "grokSessionId": "", + "toolInputDigest": "sha256:...", + "receiptHash": "sha256:...", + "attempt": 1, + "taskDigest": "sha256:...", + "resultDigest": "sha256:...", + "toolCallId": "", + "sessionEvidenceId": "", + "proofId": "", + "acceptedRevision": 12, + "checkpointRevision": 17, + "journalHeadDigest": "sha256:...", + "evidenceRefs": [""] +} +``` + +不得把 JSON 中的 `sessionEvidenceId`、`proofId` 写成模型自报的来源。样例数字没有实际验收含义。 + +`flowkitRequestId` 对应现有 M5/Coordinator receipt 的 `requestId`,而 `grokRequestId`/`grokSessionId`/`toolCallId` 只来自受保护工具事件。`toolInputDigest` 比较工具输入与收到的参数;`receiptHash = sha256(canonicalBytes(normalizeHostAgentReceipt(receipt)))` 必须由 Host 从当前 Pending 和受信参数构造。不能将这两个摘要混成一个,也不能以 Grok requestId 查询 FlowKit 历史 Ack。 + +其他强制材料: +1. exact program bytes/hash、run/receipt/Journal 与源代码 commit; +2. Grok Build 原始工具调用/工具结果事件,不仅是 Grok 自己写出的总结; +3. OS principal/ACL/服务权限与实际拒绝访问日志; +4. Host evidence ledger 的事件身份绑定、签名语句与 verification 结果; +5. Crash/Recovery/Concurrency 的真实进程和 SQLite 事务记录; +6. C01–C24 逐项分层裁决与失败/阻断项; +7. 原始密钥、完整私有 State、密钥/证书私钥绝不写入报告或模型通道。 + +## 6. 关闭问题和裁决流程 + +流程为:**冻结复现 → 执行 → 检查原始证据 → Finding → 修复 → 重跑受影响项 → 全量回归 → 独立复审**。 + +- PASS:对该环境和等级的所有适用断言均有证据。 +- FAIL:已复现缺陷。 +- PARTIAL:只覆盖部分真实路径。 +- BLOCKED:前置环境或信任证据不足。 +- DEFERRED:仅当已批准放到明确后续阶段。 +- 同一项不得在不同 commit 的日志之间拼接成一个 PASS。 +- CI PASS 不等于原生 N PASS。 +- **Phase 3 安全 P0 未通过,绝不能进入 NAT 实验并声称安全原生宿主。** +- 对外部 Agent Provider 不承诺 exactly-once;只承诺 Store 状态/CAS 至多一次有效提交。 +- 最终 C12/S13 如果缺原生工具事件或来源绑定,必须仍然 BLOCKED。 + +## 7. 独立审查要求 + +审查者应重点检查: +- 设计里有没有模型可写/读的 Host 凭据或 State; +- 是否把 mTLS client 证书当作模型回复证据; +- 是否把 `usage.signature` 当作可验证 Provider 证明; +- 是否在 Windows 仅依赖 `net.createServer` 的默认 Pipe DACL; +- 是否修改了 P0-A ABI 或 SDK 签名 v1; +- 是否允许模型自建工作流并自己授权 Program; +- Host 回执是否始终由独立观察结果而非普通 JSON 生成; +- 每条高危负例是否能够在真实 OS 用户/进程上执行; +- C12/S13 是否有真正的 native JS tool-call 原始日志; +- 是否存在遗漏、重复/互相矛盾的通过条件; +- GitHub CI 是否真的对应 exact HEAD。 + +只有技术设计和本矩阵经复审同意,才创建 Phase 3 代码 PR。不因文档 CI 绿灯提前实现 Windows 服务或 Host IPC。 diff --git a/docs/interactive-trusted-host-security-v2-design.md b/docs/interactive-trusted-host-security-v2-design.md new file mode 100644 index 0000000..6542df7 --- /dev/null +++ b/docs/interactive-trusted-host-security-v2-design.md @@ -0,0 +1,347 @@ +# FlowKit Interactive — Trusted Host V2 安全与原生 Grok Build 桥接设计(Draft) + +> **阶段:Phase 2 / Design only。2026-11-11。** +> +> **代码核对基线:** `main@9bac8f86347a405efe068f96423ae3e501005061`。历史确认的 V0.3 需求与 V0.6-R5 设计原件在当前审查可用文件/仓库中未找到,完整 SHA-256 也不可核验;两份原文的符合性维持 BLOCKED,不以路线图摘要冒充原件。当前可核对基线是 M5 安全契约 [interactive-host-security.md](./interactive-host-security.md);M6 完整路线 [full-delivery-roadmap](./interactive-full-delivery-roadmap-2026-11-11.md)。 +> +> **状态:第三轮 Grok Build 定向复核已关闭 F-01 与 F-R2-01 的设计矛盾;整体仍为 Draft / Phase 2 条件状态,不是已批准实施或已验收功能。** F-02 原生工具绑定、F-04 跨主体句柄隔离仍待实测,F-07 正式 V0.3/V0.6-R5 原文符合性仍 BLOCKED。本文没有批准修改 Core、Program ABI、SQLite Schema 或现有 SDK 导出。发现需求/安全契约冲突时必须先处理差异。 +> +> **目标宿主:** Grok Build 首选,未来 ChatGPT / Codex / Claude Code 使用同一个宿主中立协议。直接 Grok Build 为首选;ACP 不是强制依赖。 + +## 0. 结论与范围 + +### 0.1 最终设计方向 + +1. **保留现有 FlowKit Core**:Compiler、签名后的不可变 JS Program、`createInteractiveCoordinator`、SQLite WAL/FULL/CAS、Journal 与历史 Ack 不重写。 +2. **保留 M5 协议**:`createTrustedInteractiveHost`、`getPublicAgentTask`、`accept({receipt,attestation})`、`createAgentReceiptStatement` 与 Ed25519 v1 canonical statement 不改变。 +3. **新增边界属于 Host Adapter / Deployment,而非 FlowKit Runtime**:受保护的 Host 进程/账户、信任配置、密钥与数据库访问控制、受限 IPC、会话与模型输出观测证据、原生 JS 工具桥接。 +4. **将三个概念分开**:OS 隔离、Host 独立观测的来源/工具调用、Provider 级可验证身份。任何一项不能靠另外两项替代。 +5. **先安全验证、再对接真实 Grok**:不允许 Grok 在能读取 Host 私钥、数据库或 Coordinator 的同权身份下充当安全验收主体。 +6. **不创建通用 Agent Runtime**:Host 是否作为受保护按需进程或服务运行,是部署适配层的生命周期问题。Core 不依赖常驻 Server。 +7. **不扩张 P0-A**:Human/Action/Verification/Loop/Parallel/通用上下文、业务产物持久化、GC、Provider exactly-once 均不在本轮实现。 + +### 0.2 威胁模型与资产 + +**受保护资产:** +- Host Ed25519 私钥 / KMS 授权; +- Host-owned SQLite 主文件、`-wal`、`-shm`、Checkpoint、Journal、receipt index; +- Program 不可变字节、可信构建清单与 artifact allowlist; +- Host policy/binding versions、tenant namespace、完整 State 和敏感业务输入; +- Host-only provider/session/tool-call 观察记录、审计密钥、IPC 认证凭据; +- 持久化的 Run / Request / attempt 绑定和历史 Ack。 + +**不可信主体:** +- Grok Build 的模型推理、可控工具调用/终端脚本; +- prompt-injected Skill、工作流任务描述、模型生成的 JSON、文件内容和第三方远程资源; +- 共享电脑上的其他普通用户/进程; +- 会被模型触及的工作区、用户家目录、宿主的 shell 工具。 + +**信任边界:** OS Token/SID/UID → Host Private FS → 可信执行器 → 受保护 IPC → Host signing → `accept` → SQLite CAS。流程描述和 JS API 包装 **均不是** OS 沙箱。 + +**明确不覆盖的威胁:** 已取得管理员/root、内核权限或可控制 Host 签名进程的攻击者;受信 Host 本身被恶意代码替换;Provider 服务端被攻破。这些属于部署根信任或事件响应范畴。若 Grok Build 进程实际拥有可随时提升到管理员的权限,则不能称为隔离通过。 + +## 1. 现有源码与已验证事实 + +| 组件 | 现状 | 证据 | 设计动作 | +|---|---|---|---| +| Compiler / Program | 产物 Hash、静态 ProgramTable、verified byte loader、零 import 校验 | `src/interactive/compile.mjs`、`src/interactive/load.mjs` | 复用;禁止模型控制 artifact allowlist | +| Coordinator | 只由 Host 执行、决定状态与路由、持久化 CAS | `src/interactive/coordinator.mjs` | 不新增模型侧可写入口 | +| Store | Namespace、SQLite WAL/FULL、Journal、历史回执索引 | `src/interactive/sqlite-store.mjs` | Store 由独立 Host 账户拥有,连 WAL/SHM 一起隔离 | +| Trusted Host M5 | `allowedInputKeys` + `authorizeDisclosure`,签名先验证后 CAS | `src/interactive/trusted-host.mjs` | 只在信任域内使用;公共工具不返回原始 Host frame | +| Receipt V1 | 已签字段包含 namespace/run/request/node/attempt/receiptHash/program/policy/proofId/times | `src/interactive/host-attestation.mjs` | **不增加**新签名字段;session evidence 通过独立 Host-only `proofId` 索引绑定 | +| Linux OS 隔离 | 真 Node `nobody` 子进程不能读取 Host 私钥/SQLite | `tests/security/host-isolation.mjs`;main CI | 已存在,只需扩展到实际原生模型 | +| M6 scripted Host | 独立 Host 与 scripted worker;projectRoot 兼容修复后主 CI 通过 | PR #13、main `9bac8f8` | 不冒充模型/来源证明 | +| Grok 实测 | 15 个真实模型结果经文件 Harness → Host;Windows 同权信任边界无有效证明 | 2026-11-11 Grok 验收报告 | M 层部分成功;C12/S13 N 层仍 BLOCKED | + +### 1.1 历史 Finding 不重复开发 + +- **N1** 确定性 FK_R002、FK_I_VALIDATOR_CONTRACT → errored:源码与测试存在,实施前只做门禁复核。 +- **N3** Program ABI/ProgramTable、静态合法转移:源码与 TypeScript 定义存在,不新增第二套解析器。 +- **N5** namespace 主键及 startKey 唯一索引:SQLite Store 已实现并有跨租户测试,不重复建租户系统;Host 进程权限仍需验证。 +- **N7** P0-A 终态 State 在 Host frame 已可读取;`contextError` 的 P0-B 扩展仍待实现。**不要将原 N7 全量误判为缺失。** +- **N8/N9/N10/N11**:零 import、只允许 P0-A Stage、package exports、Agent Pending name/overview 已有源码路径与测试,核查而非重做。 +- **N6**:不可变 Program 字节已持久化,但**跨 SDK 版本升级 + 在途运行**专门实验尚未覆盖;保留既定阶段。 +- **N12**:现有 `stableTransitionId` 为确定性;P0-B Action operationId/reconcile 和 P1 并行冲突尚未实现。 +- **N2/N4/N13**:按既定 P0-B 门禁保留。Human provenance 不能由当前模型提交 Agent 回执代替。 + +## 2. 目标部署拓扑 + +```text +UNTRUSTED Grok Build / Codex / Claude / ChatGPT + OS principal: MODEL_USER (non-admin) + model + ordinary tools + optional configured MODEL_USER MCP tool + never holds signer, private Store or Host TCB credentials + | + | (1) native tool_call rawInput/event: Host-captured CLI stream + | (2) candidate result: constrained untrusted local transport + v +TRUSTED HOST SUPERVISOR / ADAPTER (single HOST_USER TCB by default) + Host captures tool events from its own CLI child pipe + verifies tool input / result / current Pending and tenant policy + approved immutable Program manifest + Host-only session evidence + secure allowlist, disclosure, bounded reconciliation and Outbox + --- private trust boundary --- + createTrustedInteractiveHost() + createAgentReceiptStatement() + Ed25519 Host signer + createSqliteCheckpointStore() -> WAL / FULL / CAS + | + v +durable next Pending / Terminal + +OPTIONAL: separate BRIDGE_USER / protected local mTLS hop only when a +deployment has a concrete need for another OS security boundary. +``` + +**Control plane vs data plane** + +- `start`/bootstrap (Program approval, initial State, tenant, policy) **仅由可信用户/Host 控制面**发起。 +- 模型数据面可见的只有 `getCurrentPublicTask`、`submitAgentResult`、`continuePublic` 等**适配层操作**。这只是拟议命名,不是新增到 SDK 的 API;最终应复用现有 `getPublicAgentTask` 和 `accept`。 +- `resumePublic` 是要求 Host 根据已认证 Run 重算并返回脱敏公共视图,不开放未经授权的原始 `resume`。 +- 现有 `InteractiveRunFrame` 是 **Host-visible**,终态可以含 `state`,绝不能无过滤转发给 Grok。模型可见终态仅含 status/terminal/可公开摘要。 +- 业务正式输出由用户/Host 的专用读取能力获取;任何该能力都不能被模型工具直接调用。 +- Host 的签名输入来自 Host **独立观察**的结果/事件,不来自模型要求“给这个 JSON 签名”。 + +## 3. Windows:可落地的安全部署方案 + +### 3.1 安全身份 + +推荐: +1. 安装时创建或选择独立 **HOST_USER**(例如受限 Windows Service SID/专用服务账户),Host 在该 Token 下运行。 +2. Grok Build 运行在普通、非管理员 **MODEL_USER**;其用户及工具子进程对 HOST_USER 私有资源必须没有访问权。 +3. 私有 Store 和签名密钥放在 Host 专有目录(例如 ProgramData 下的专有子树),通过显式 DACL/Owner 控制;**检查主 DB、WAL、SHM、备份/日志、产物、配置和目录本身**。 +4. Host 服务控制权限必须防止 MODEL_USER 重启为任意代码、修改服务可执行文件、修改配置或向 Host 注入调试/进程访问。 +5. `Get-Acl` / `icacls` 和实际以 MODEL_USER 身份进行的读取、写入、重命名、替换、子进程及进程访问负例必须一起通过。 +6. UAC 提示、用户同意、管理员/root 权限不可被当作“自动隔离能力”。**如果 Grok Build 仍以管理员 Token 运行,就 BLOCKED。** +7. Supervisor 启动 MODEL_USER 时仅允许继承必要的匿名 stdout/stderr/明确授权的通信句柄,不得继承 Host 私钥、SQLite 主库/WAL/SHM、证书、配置、文件映射、进程/Token 句柄或机密环境变量。Windows 使用不继承句柄或经审查的显式句柄白名单。**实际子进程句柄表和跨账户测试**必须与路径 ACL 拒绝测试同时通过。 + +Windows 文件访问检查依据微软 ACL / File Security 文档。单纯设置 `chmod 0600` 或把路径命名为 `host-private` 不作为 Windows 隔离证据。 + +### 3.2 IPC 传输基线选择(ADR-H2) + +**最小受信部署仅强制两套 OS 身份:MODEL_USER 与 Host TCB。** Bridge、Supervisor 与 Host 在同一 HOST_USER 内可合并为一个受保护进程,不强制在同一 TCB 内增加一跳 mTLS。仅在部署需要跨进程本地监听端点时,才选用 `127.0.0.1` TLS/mTLS;此时必须证明传输身份与原生工具事件的分离,ACP 不是必要前置。若使用 TLS/mTLS,要求: +- `127.0.0.1` 单独绑定(如需要 IPv6,明确独立回环绑定并认证);禁止 `0.0.0.0`、LAN、自动外网暴露。 +- TLS/mTLS 要求 `requestCert=true`、`rejectUnauthorized=true`、服务端证书身份固定、CA/客户端证书指纹白名单。客户端证书仅证明本地通道身份;如果客户端进程在 MODEL_USER 下运行,其凭据可被模型读取,绝不能作为 Model/Provider 原生来源证明或 Host 签名授权。Host-only 密钥仍由 HOST_USER 持有。 +- 服务端的 Host 私钥与 Ed25519 回执私钥均仅在 HOST_USER 访问域。 +- 客户端凭据只授权非常窄的 bridge 操作;**客户端拥有凭据 ≠ Provider/模型身份认证**,不允许以“mTLS 成功”直接给模型结果签署原生来源证明。 +- 每个连接再经 Run/tenant/operation/taskDigest/requestId/attempt 绑定授权,必须检查终态、漂移和 replay。 +- 使用有界长度前缀帧、idle/read 超时、并发上限、严格 JSON schema,拒绝未知字段;针对 P0-A 的 2 MiB signed receipt 上限重新计算传输尺寸,不能靠截断输出制造错误分类。 +- 如果 Host 采用按需启动而非长驻进程,端点随 Run/调用按需生存;这不是 Core 的通用 Runtime。 + +### 3.2.1 最小信任边界及可选两跳通道(DR-01 / F-02) + +不能把 **Host TCB 专用** mTLS 私钥交给 Grok Build 工具脚本:MODEL_USER 可复制其有权读取的凭据。模型侧候选连接若存在单独的客户端身份,其只能用于传输访问,绝不能代替模型来源证明。受信路径为: + +1. **MODEL_USER 原生工具调用 → 不可信数据入口。** 模型只传公开 Run/flowkitRequestId 与 result;该入口不持有 Ed25519 signer、Host TCB 的 mTLS 私钥或 Store。即使拥有模型侧传输凭据,JSON 仍然只是候选数据。 +2. **HOST_USER 控制的 Supervisor → 验证真实 native `tool_call` 事件。** Supervisor 从其保护的捕获通道获得 CLI 进程、Session 与 tool-call 事件,将它和入口收到的候选结果按 Run/RequestId/Attempt/ToolCallId/Hash 严格匹配。 +3. **Host TCB 校验后才签收。** 受保护 Bridge 与 Host 若为同一 HOST_USER,可直接走内部受限调用;独立 Bridge 进程或 loopback mTLS 是部署选项,不是第二个独立信任域。任何输入候选只有与 Host 独立观察到的工具事件绑定后才可签名。 +4. **Host 签署后才允许状态推进。** 任何观察链断裂、乱序、事件无法关联、超时或权限错误都不能发出 Host 签名和 CAS。 + +模型→Host TCB 的候选入口可以是受限 MCP/Node 工具与本地 IPC;该入口不被当作认证事实来源。**禁止**把所有 CLI 工具调用事件视为已被 Provider 数字签名。 + +此结构不要求修改 FlowKit JS Program 或核心 SDK;它仅在宿主部署层实现更强的证据收集。**受保护 Bridge 与 Host Adapter 同在 HOST_USER 时属于同一个可信计算基(TCB)**:模型工具无法读取或调用两者的私有资源,但不能宣称“Bridge 被 OS 阻止读取 Host signer”。若安全目标进一步要求即使 Bridge 被攻击也无法读取 Host key/DB,必须部署独立 BRIDGE_USER 并对 Host 目录与 signer 进行真实 ACL/UID 隔离;它是可选的更强隔离配置,不能靠进程名称或 JS 对象封装假装实现。当前 M6 原生硬门禁首先证明 **MODEL_USER 与整个 Host TCB** 的真实隔离。 + +**Named Pipe 作为可选 Windows 原生优化**,不得无审查替换上面的方案: +- Node `node:net` 支持 Windows named pipe,但“能 `listen(path)`”不证明 DACL 正确。微软官方说明默认描述符向 Everyone 和 Anonymous 授予读取权限,因此未提供自定义 DACL 的默认 `node:net` Named Pipe 禁止作为安全 IPC。Grok 报告中的具体 Windows Node SDDL 测量未附原始脚本,本轮不将其记作我已重现。 +- Windows `CreateNamedPipeW` 可以在 `SECURITY_ATTRIBUTES` 中提供安全描述符;默认 DACL 可能给 Everyone/Anonymous 读取权限。 +- 如选 Named Pipe,必须用经审查的 OS 原生启动/安全辅助模块,明确控制 DACL/SDDL、服务 SID、可访问的客户端 SID、`PIPE_REJECT_REMOTE_CLIENTS`,并验证连接方的实际 Token/SID;不能只根据 PID、管道名字或随机路径判断授权。 +- Node 22/24 公开 `server.listen({path,readableAll,writableAll})` 没有直接设置自定义 SDDL/服务 SID 的选项,不能从 `readableAll:false` 推断默认 DACL 安全。若选 Named Pipe,必须在创建时提供明确 DACL 和客户端身份校验,并用真实 Windows 测试验证;不得在宽松创建后补改权限。 + +两种传输都不是模型来源证明;传输认证只证明授权通信主体。需配合 §5 的可信观察。 + +## 4. Linux:对应安全方案 + +1. HOST_UID 与 MODEL_UID/GID 分离,MODEL_UID 不得为 root、不得拥有 `sudo`、`CAP_DAC_OVERRIDE`、调试 Host 的能力。 +2. Host-only 私有根目录 `0700`,密钥 `0600`,数据库及 WAL/SHM 继承相同隔离;公共 Task 由 Host 明确披露。 +3. **仅在确实启用相应监听端点时**采用 loopback TLS/mTLS 或 Unix Domain Socket,并审查对应证书、端点所在目录、所属组、权限、Peer Credential 与符号链接/路径替换风险。最小单 Host 进程方案不要求创建网络监听。 +4. 测试 MODEL_UID 的文件读取/写入、目录遍历、pid/fd/env 访问、Host 进程调试/注入、IPC 伪造、跨租户访问。 +5. 现有 `tests/security/host-isolation.mjs` 只能证明**脚本模型子进程**的 Linux UID 边界;真实 Grok Build 对应进程仍需同样的测试和进程证据。 +6. 不把 Docker 非特权容器、WSL2 或运行时目录名本身当作安全隔离,除非隔离配置经过实际攻击测试。 + +## 5. 来源证明和真实模型调用证据(ADR-H3) + +### 5.1 证据等级,不得混淆 + +| 级别 | 已证明事项 | 不能宣称的事项 | +|---|---|---| +| P / scripted | Compiler → JS Program → Host/SQLite、协议测试 | 真实模型行为 | +| M / live-model | Grok Build 当前会话确实在真实 Pending 后作答,有工具事件/输出 | 模型/Host OS 隔离、Provider 加密来源证明 | +| T / host-observed transport | 独立 HOST_USER 通过受保护会话/IPC 观测到指定 CLI 进程和工具事件,并绑定该响应 | 供应商端对会话/回答的数字签名 | +| N / native-host-attested | 冻结 C12/S13 所需全部原生工具链 + 可信来源与隔离证据、Host 和 Store 不变量 | 不覆盖管理员攻破或 Provider 内部事件 | +| V / provider-verifiable(如果供应商支持) | 供应商可公开验证规则和可信根支持的响应来源证明 | 不能由 Grok 普通 JSON `signature` 字段推断 | + +**证据身份不能由模型随意填写。** Host-only evidence ledger 的事件必须由不受模型写权限控制的可信 Transport/Supervisor 记录。 + +### 5.2 直接 Grok Build CLI 可复用的证据 + +xAI Grok Build 文档提供: +- 交互模式 `grok`; +- headless `grok -p ... --output-format streaming-json`; +- streaming-json 的 `tool_call`、`tool_call_update`、`usage`、`end` 等事件,以及在部分后端可用的 `sessionId`、`requestId`、`toolCallId`。 +- 不同后端不保证完全相同的来源或签名字段;`usage.signature` 不能未经官方验证规范、密钥和签名范围确认就称作 Provider attestation。 +- 不要求 ACP;如果以后 Host 需要稳定、长期操纵多个会话,再评估 ACP,但 **不能因为切换 ACP 就放宽隔离和来源门禁**。 + +**安全验收模式**推荐由受信 Host Supervisor 启动受限的 Grok Build CLI,固定二进制位置/Hash、配置、允许的工具集合、CWD、运行账户;捕获 CLI 原始结构化事件流。捕获通道和证据目录应仅 HOST_USER 可写。运行环境不得允许模型修改其自身被测 CLI 二进制或 Host 端记录。 + +如果只是用户现有 Grok Build 交互窗口自行写文件、模型填写 `GROK_SESSION_ID`、或同一 OS 用户运行 Host,自然可执行 M 层试验,但 **不能充当 N 层安全验收**。 + +### 5.3 绑定算法和 Host 回执签署前置条件 + +1. Host 持久化当前 Run 和 Pending,建立不可变 `{namespace,runId,nodeId,flowkitRequestId,attempt,artifactHash,policyHash,taskDigest}` 索引。`flowkitRequestId` 映射为原 M5 receipt 的 `requestId`;Grok CLI 的 `grokRequestId/grokSessionId/toolCallId` 保留为另外的 Host-only 观察字段,不能覆盖 FlowKit 身份。 +2. Trusted supervisor 创建 Host-only `sessionEvidenceId`(不是模型输入),记录实测 CLI binary Hash、OS principal、启动时间、进程树、Grok 会话标识(若提供)、工具 invocation/update 事件、原始输出 digest、requestId 绑定和事件的单调序号。 +3. 当 Grok Build 通过原生工具提交结果时,Bridge 只发送结果数据和公开 request identity。Supervisor/Host 通过**独立捕获的真实工具事件**及当前 Pending 核对 ToolCallId、`toolInputDigest/receiptHash`、会话/进程通道、租户权限、时效和容量。 +4. **先捕获调用开始,再签署回执。** 对 `submit`,Host 必须在工具执行前独立捕获真实 `tool_call` 事件(携带完整输入参数或可验证摘要),与 Bridge 候选结果匹配。不能等待 `submit` 结束后才出现的 `tool_call_update` 或工具最终输出再签署,否则会形成“工具等待 Host,Host 等待工具”的死锁。完成事件用于签后审计;如果 Grok 当前版本无法证明开始事件时序,需要在 Phase 4 改为显式双阶段协议,不能假设已有能力。 +5. 如果某个事件无法可靠证明对应当前结果、会话/进程或授权工具执行,**不得签署 Agent 回执**;保持原 Pending,写 Host-only 审计并按受控恢复策略处置。 +6. Host 归一化 `normalizeHostAgentReceipt(receipt)` 后,建立 Host-only `proofId → verifiedSessionEvidence` 绑定,选择已核准的 `keyId`,调用现有 `createAgentReceiptStatement` 和 `encodeAgentReceiptStatement` 在 HOST_USER 下签 Ed25519。 +7. 最后调用现有 `host.accept({receipt,attestation})`。现有 statement 的 `proofId` 和 `receiptHash` 正好绑定已认证事件与结果;**不新增 v1 ABI 字段**。 +8. 原始证据若是任何模型可写的 JSON,则只能作辅助上下文,不是独立认证来源。 +9. `agent-call-failed` 和 provider output-overflow 只在 Host 可信观察到真实失败/限制后签发,禁止把任意模型自报失败升级为可信状态变更。 + +### 5.4 对可验证性边界作出硬判定 + +- 若受控 CLI 输出只证明“本机特定进程输出”,而无法独立证明内部 Provider 服务端实际产生该响应,证据只能记 `HOST_OBSERVED`,不能虚构 `PROVIDER_VERIFIED`。 +- C12/S13 的最终等级必须依照冻结验收条款判定。若条款明确要求 Provider 级来源且 Grok 没有可用的可验证机制,标 `BLOCKED` 并提交具体差异供审查,**不能降低验收要求**。 +- 同一用户运行的普通 CLI、文件轮询、模型自报身份及 Host 自签未经校验的 JSON 都不能解除 C12/S13。 +- 对于 ChatGPT/Codex/Claude 的后续适配,要求同样证据等级,并逐宿主声明不足;不允许为了平台兼容以通用伪 provenance 填补空白。 + +### 5.5 直接 Grok Build 工具注册与结果证据(F-02) + +1. `--tools` 是内置工具 allowlist,**不会注册自定义 FlowKit JS 函数**。首选探针为在受信安装的 Grok `.grok/config.toml` 中配置受限的 **MCP FlowKit 工具服务器**,该服务器运行于 MODEL_USER 且不持有 Host 私钥、SQLite 或 signer;备选固定 Node/Shell 命令只有在能提供同等级原生输入事件证据时才可用。实际 MCP 工具的发现、启用、授权及 `tool_call.rawInput` 形式须实测,不能凭文档声称完成。 +2. 受信 HOST_USER Supervisor 只从自己掌控的 CLI stdout 捕获结构化事件;模型和工具 stdout 的伪造/混淆能力通过 NAT-06/14 攻击实测排除。模型侧 MCP 工具发出的候选 RPC 是不可信数据,`--tools`/MCP 的存在本身不构成来源认证。 +3. **两个摘要分别定义**:`toolInputDigest = sha256(canonicalBytes(rawInput))`,对比 Host 独立捕获的原生 `rawInput` 与 MCP 候选 RPC 参数;Host 根据当前 authoritative Pending 创建 `normalizedReceipt`,然后 `receiptHash = sha256(canonicalBytes(normalizedReceipt))`。必须从上述两条已验证输入路径重算出**相同 normalizedReceipt 与 receiptHash**,不是要求 `rawInput` 原文逐字节等于包含 Host 补充字段的完整回执。Grok 的 `grokRequestId`、`grokSessionId` 与 FlowKit 的 `flowkitRequestId` 不可互换。 +4. 入参规模应实测 64 KiB、256 KiB 和接近合法回执上限的边界。2 MiB 是 M5 Signed Receipt 的**上限**,不是 Grok/MCP 保证支持的参数量。若 CLI 起始事件丢失/截断参数,或结果走模型可替换文件而只看到命令字符串,签名必须 BLOCKED;必要时另审 Host-owned immutable buffer + 对应可验证事件摘要的两阶段协议,不允许隐式降级。 +5. 工具 `start/getPending/submit/continue` 是 Host Adapter 的行为映射,不是新增 FlowKit Core 公共 API。`start` 只能启动经可信用户预授权的 Program/State,不允许模型创造 allowlist 条目;`continue` 返回脱敏状态,不输出 Host frame 完整 State。 + +## 6. IPC / JS 工具契约(Host Adapter Proposal,不修改 SDK) + +### 6.1 API 角色隔离 + +| Adapter 操作 | 发起主体 | Host 动作 | 返回内容 | 关键禁令 | +|---|---|---|---|---| +| `bootstrapRun` | 受信用户/部署控制面 | 校验不可变 Program/policy,调用 Host `start` | Run 身份和私有管理 Ack | 模型不能上传 Program Hash 并自动加入 allowlist | +| `getCurrentPublicTask` | 已认证 Grok Bridge | 检查 Run/tenant、`getPublicAgentTask`、授权披露 | 只含当前白名单 Task + adapter correlation | 不返回 Host frame、完整 State、私钥 | +| `submitAgentResult` | 已认证 Grok Bridge | 关联独立 session/tool evidence → Host 签 receipt → `accept` | acceptedRevision/duplicate/status(脱敏) | 模型不能提交签名、proofId 或 Host policy | +| `continuePublic` | 已认证 Grok Bridge | 检查 Run 归属,Host `resume` 并重新授权披露 | next Public Task 或脱敏终态 | 不调用原始 Coordinator `complete` | +| `getRunStatus` | 已认证受限调用方 | Host 私有 `load` 或安全状态派生 | status、revision、可披露摘要 | 不外发完整 State | +| `readPrivateResult` | 受信用户/Host 控制面 | 按用户策略读取 Host-visible 终态 | 受授权业务 State | 不注册成模型可用工具 | + +**对 `start` 的含义**:用户原始的 S13 流程包含 Grok 调用 JS 工具启动工作流;真实工具 `bootstrapRun` 的入口必须已由受信用户明确授权初始 State、Program 与 Run scope,不能给模型任意启动新 Run 的权限。模型可以触发“已授权 run 的 start”,不拥有“授权一个新工作流”的权力。 + +### 6.2 Transport envelope 草案 + +```json +{ + "protocol": "flowkit.host.bridge.v1", + "operation": "submitAgentResult", + "correlationId": "host-allocated-or-non-authoritative", + "runId": "run-id", + "flowkitRequestId": "req-id", + "attempt": 1, + "payload": {"result": {"summary": "..." }} +} +``` + +说明: +- `correlationId` 只用于可观测性,不是认证材料; +- `flowkitRequestId` 是 FlowKit 当前 Pending 的身份,适配器映射成已有 receipt `requestId`;Grok `grokRequestId/grokSessionId` 仅为 Host-only 观察字段,不得覆盖它; +- 真实桥接器应使用 strict key allowlist、受控 JSON/UTF-8 解析、长度前缀帧、deadline、连接并发限制和生命周期清理; +- `namespace`、`artifactHash`、`policyHash`、`nodeId` 从 Host 当前 Pending 读取,模型提交的同名字段不能改变它们; +- Host 把调用绑定到已验证 OS 客户端 principal、授权租户和当前 Run;错误 Run/Request/attempt、越界字段均拒绝; +- 具体传输 body 上限需与既有 v1 receipt **2 MiB** canonical limit、Checkpoint active reserve、Skill 输入范围协调,经实测冻结;超限发生在签名前按现有三类故障分类处理,不允许随意截断; +- 未认证请求、非法 JSON、签名错误和 stale Pending **零 CAS、零 Journal、零 receipt index 变更**; +- 不得把 `getPublicAgentTask()` 返回的敏感以外字段扩张为任意 State 全量读取; +- 用户中止/断线不能凭模型 JSON 直接写入“Human 批准”或“取消”终态,P0-A 只处理合法 Agent 回执。 + +### 6.3 错误和恢复 + +- 新增 Adapter 错误只限宿主传输诊断,不改 FlowKit 的既有 `FK_I_*` 错误集合;需要新增 SDK 错误码时必须另签设计变更。 +- 掉线/Host 崩溃:保存证据链和原 Pending;重启时通过现有 `resume` + `getReceipt` 对账。不得声称 Provider exactly-once。 +- 同内容重复提交 → 原 acceptedRevision;不同内容同 requestId → `FK_I_RECEIPT_CONFLICT`;迟到或错租户按原协议拒绝。 +- 策略/密钥轮换:保留已批准旧运行的身份/密钥策略直到 Run drain;无法提供安全迁移时 fail closed,不得重签一个编造的旧回答。 +- 缺来源证据、隔离破坏或私钥访问异常时停止签署新 receipt,Store 保持在可审查的最后 durable State;不能用无穷重试假装恢复成功。 +- 详见 §6.4 对签后、CAS 前进程崩溃的 Outbox 和过期证明处理;禁止无持久证据的重签。 + +### 6.4 Host-only 观察证据与签名回执 Outbox(关闭 DR-13) + +**必须解决的故障窗口**:模型结果已被独立观察、Host 已签 v1 statement,但 `host.accept()` 还没提交持久回执就崩溃。如果签名已过期,M5 仅允许**已接纳、内容相同的回执**在过期后复用历史 Ack;**未接纳的过期回执不能直接重放成功**。 + +实现约束: + +1. Host-only observation ledger 使用独立保护的持久存储(可为 Host Adapter 自己的 SQLite/附加表;不得未经批准改变 FlowKit Core Store Schema),记录受信工具事件摘要、`namespace/runId/flowkitRequestId/attempt/taskDigest/toolInputDigest/receiptHash`、Grok 的独立 `grokRequestId/grokSessionId/toolCallId`、CLI 进程、来源级别及审计 ID;`receiptHash` 与现有 `createAgentReceiptStatement` 对 `normalizedReceipt` 规范化后的 SHA-256 完全一致。Outbox 使用 SQLite WAL + `synchronous=FULL` 或已证明等效的 durable fsync 屏障。 +2. 在调用 signer 前先持久写入 `OBSERVED` 事件与验证结果。签名成功后,**先持久写入完整的 signed statement/receipt 和 `SIGNED` Outbox 记录**(Host-only,保留原始字节),再调用现有 `host.accept()`。不能在内存里签完就立即调用,留下不可对账的崩溃窗口。 +3. 若 `accept()` 成功,核实 Store 的 `getReceipt(runId,requestId)` 与 v1 `receiptHash/acceptedRevision` 相同后,标记 `ACKED`。如果此时又崩溃,重启时从 Store 核对后补写 `ACKED`,不能产生第二次业务 State 提交。 +4. 若崩溃后为 `SIGNED` 但 Store 尚未接纳:**未过期**则原字节重放;**已过期**则保持 Pending,不得拿过期证明绕过 M5。只有 Host-only 原始证据仍有效、当前 Pending/namespace/Program/policy/attempt 未变,且 Outbox **持久保存的原始 normalizedReceipt canonical bytes 与 receiptHash 完全一致**时,才允许按审计规则在同一 proofId 与同一业务回执字节上生成新的签发时间/签名;不能从模型重新序列化或推断出另一份结果。已接纳的相同回执始终走原历史 Ack。否则 `BLOCKED/RECONCILE`。 +5. `proofId` 应由 Host 独立分配,映射到不可变证据记录;必须限制同一 toolCallId/事件/结果在不同 Run、租户、attempt 之间复用。 +6. 对冲突的两个合法结果,现有 Coordinator CAS 仍决定唯一有效提交;Outbox 记录未中标的结果必须标记 `CONFLICT/REJECTED`,不能“清理失败结果”时丢掉必要审计。 +7. Outbox 保留策略应与 Run 生命周期、合规审查窗口、敏感数据最小化和存储上限绑定;默认禁止无限制记录完整模型文本、私钥、完整 State。实际保留时长/GC 策略作为 Host 部署配置在 Phase 3 验收中冻结,**不是**新增 FlowKit Core 通用业务产物库或 GC。 +8. 必须测试 `OBSERVED→SIGNED`、`SIGNED→ACCEPTED`、`ACCEPTED→ACKED` 的真实进程强杀、错租户、超期签名、重复回复、签名轮换与审计 Outbox 恢复,并证明 Journal/Checkpoint 不被 Outbox 重建逻辑重写。 + +这个设计避免把“Host 自己可以重新签名”误当成持久恢复与 Provider exactly-once 证明,也不改变现有 M5 对过期证明与历史 Ack 的安全语义。 + +## 7. 部署与运行模式 + +| 模式 | 实际用途 | 可宣称层级 | +|---|---|---| +| Developer Mode | 用户直接打开 Grok Build,手工读 Pending/写 response,Host 可共享普通用户进程 | 仅 P/M;**不能**通过 N 层安全门禁 | +| Secure Windows Host | HOST_USER 与非管理员 MODEL_USER 分离;私钥、SQLite/WAL/SHM、服务控制和继承句柄均有实际拒绝证据;启用任何候选数据入口必须完成身份/权限/伪造测试;**不要求默认开启 mTLS 或监听端口** | Phase 3 的 OS 安全按 Windows Profile 单独裁决;只有真实观察工具事件后可申请 T,完成 C12/S13 才可 N | +| Secure Linux Host | HOST_UID 与 MODEL_UID 分离;0700/0600、数据库及子进程句柄保护实测;任何已启用的候选数据入口需按真实传输方式安全验收;**不强制启用 TCP/mTLS/UDS 监听** | Phase 3 的 OS 安全按 Linux Profile 单独裁决;只有真实观察工具事件后可申请 T,完成 C12/S13 才可 N | +| Unsupported Host | 没有 JS 执行工具、不能隔离、不能绑定来源 | `NO_JS_EXECUTOR` 或 `BLOCKED`,不得回退模拟 | + +**最小安装原则**:运行时只要求目标 Host 环境已有 Node 22.13+,Host 适配可作为按需子进程;Windows 独立服务账户部署需要一次性管理员配置,不代表每个用户一个独立服务器。对于多用户 Host,租户 `namespace` 必须与 IPC 的经认证身份绑定,而不是接受模型自报 tenant。 + +## 8. 实施拆分(Phase 3/4,不在本 PR 动工) + +| 序号 | 独立交付 | 最小改动目标 | 前置 | +|---|---|---|---| +| H3-01 | Host bootstrap/provisioning | Windows/Linux 受保护 OS 身份、Host-only 私有目录、密钥/数据库及启动句柄白名单 | 本设计独立复审通过;不依赖 Grok 工具 PoC | +| H3-05 | **OS-only negative-security tests** | Windows ACL、Linux UID、进程/Token/继承句柄、Host 私钥/SQLite/WAL/SHM 实际拒绝访问 | **仅依赖 H3-01**;不运行 Grok 工具 PoC、不等待 H3-02/H3-03/H3-04 | +| H3-02 | Grok 工具/Transport adapter | 模型侧受限 MCP 工具优先;决定真实候选数据通道后再实现有界 IPC(可选 loopback mTLS) | H3-01 + **工具注册与签前 `tool_call` 最小能力探针(只记 PoC,绝不冒充 NAT-14 正式 PASS)** | +| H3-03 | Trusted observation / signed receipt Outbox | Host-only 进程/会话/tool/event/receiptHash 关联;OBSERVED/SIGNED/ACKED WAL/FULL 持久化、过期/重签与历史 Ack 对账 | H3-02 | +| H3-04 | M5 signer integration + adapter security regression | 按 `proofId` 核对证据,签 v1 statement 后 `accept`;**在已启用候选通道上验证 SEC-05/06/08/10/15/18 的 P0 负例** | H3-03 与 H3-05;H3-04 完成前 Phase 3 不得宣称整体 PASS | +| H4-01 | Grok CLI native tool observer | 基于 H3-02 PoC 固定 streaming-json 事件、toolCallId/input 摘要及日志伪造防护 | Phase 3 整体安全退出条件已满足 | +| H4-02 | Direct Grok JS/MCP tool loop | 启动授权 Run、获取 Pending、提交结果、续接终态;不得绕过 Host signer/Store | H4-01 | +| H4-03 | Native Grok adversarial acceptance | S13/C12、kill/resume、双会话、提示注入和大输出 | H4-02 | + +上述编号仅表示交付片段,不新增正式阶段。每个片段有独立测试/审查并保留失败反例。未来可切换其他 IPC 实现,但要保持相同权限与身份断言。 + +## 9. 明确的设计判停和升级条件 + +**不得进入 Phase 3 的条件:** +- 未决定可信 OS 主体、私钥/DB 的真正访问控制; +- 把 Node `net.createServer` 默认 Windows Named Pipe 当成已证明 ACL; +- 让模型或同一权限的 Bridge 获取 Host 原始 Store/Signer; +- Host 在独立验证来源前签署任意模型 JSON; +- 把 `usage.signature`、`GROK_SESSION_ID`、普通日志或 mTLS client 证书直接当成 Provider 签名; +- 新设计与现有签名 v1、Program ABI、PolicyHash 或只读/公开视图冲突; + +**完成 Phase 2 的条件:** +1. 完成独立安全复审(至少一次对抗性核验,本轮模型自审不得自称外部独立)。 +2. 冻结 OS 身份、认证、最小 IPC、Host-only session evidence、签名与恢复策略。 +3. 每个威胁有可复现负例、PASS/FAIL/BLOCKED 分类和最小修复入口。 +4. Phase 2 不要求真实 Windows/Grok 运行 PASS;Windows/Linux 权限实测属于 Phase 3 退出门禁,Grok 工具输入与时序探针是 H3-02 实施前置,NAT-14 在 Phase 4 正式验收。 +5. 任何外部 Provider 证明能力不确定时记录为“需在 Phase 4 实测”,不得作为默认已支持。 + +### 9.1 唯一阶段入口与出口(F-01) + +- **Phase 3 入口**:安全设计独立复审已通过;Host/Model 两套 OS 身份及 Key、SQLite、WAL/SHM、ACL 规则已冻结,禁止默认 Node Named Pipe 当作安全 IPC。无需预先运行 Grok 原生工具。 +- **Phase 3 退出**:H3-05 的 Windows/Linux OS 负例、H3-04 的实际候选通道/签名/恢复负例及两个 Secure Host Profile 全部适用 SEC P0 均有独立证据;单平台通过只计该 Profile,不宣称 Phase 3 整体完成。未启用监听端点时应记录 `NO_LISTENER` 与不适用的网络用例,并实测实际存在的候选数据通道,不得为刷测试人为创建 TCP/mTLS 服务。 +- **H3-02 开工前**:执行单独的**工具注册与签前 `tool_call` 最小能力探针**(非 NAT-14,不计正式验收 PASS),确认所选 MCP/受限工具的真实注册、可观测输入及事件时序具备实施条件;做不到则仅 H3-02 BLOCKED,H3-01/H3-05 的 OS 安全工作不受影响。**NAT-14** 只在 Phase 4 基于实际原生 Host 运行后正式执行并裁决。 +- **Phase 4 入口**:Phase 3 退出门禁通过、原生工具和 NAT-14 时序可实施。正式 C12/S13 原生闭环只能通过 Phase 4 的真实证据放行。 + +## 10. 官方资料及解释边界 + +- [FlowKit M5 existing security contract](./interactive-host-security.md) +- [FlowKit M6 roadmap](./interactive-full-delivery-roadmap-2026-11-11.md) +- [Microsoft: named pipe security and access rights](https://learn.microsoft.com/en-us/windows/win32/ipc/named-pipe-security-and-access-rights) +- [Microsoft: CreateNamedPipeW SECURITY_ATTRIBUTES / PIPE_REJECT_REMOTE_CLIENTS](https://learn.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-createnamedpipew) +- [Microsoft: icacls / file DACL](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/icacls) +- [Microsoft: restricted tokens](https://learn.microsoft.com/en-us/windows/win32/secauthz/restricted-tokens) +- [Node.js: IPC support](https://nodejs.org/api/net.html#ipc-support) +- [xAI: Grok Build overview](https://docs.x.ai/build/overview) +- [xAI: Headless & Scripting](https://docs.x.ai/build/cli/headless-scripting) +- [xAI grok-build: streaming-json event types](https://github.com/xai-org/grok-build/blob/main/crates/codegen/xai-grok-pager/docs/user-guide/14-headless-mode.md) + +仅在微软文档支持的范围内断言 Windows ACL/Named Pipe;仅在 xAI 文档支持的范围内断言工具事件存在。**没有公开的证据证明 Grok 的 `usage.signature` 可以直接用于独立 Provider-origin 验证。** + +--- + +**设计结论:** 采用“MODEL_USER 与受保护 HOST_USER/TCB 分离 + 文件/服务/句柄权限验证 + Host-only 原生工具观察与证据索引 + Ed25519 receipt v1 + FlowKit Core 不变”的最小安全形态。**不强制 Bridge 独立进程、TCP 监听或 mTLS**;仅在实际部署存在监听端点时按相应传输方式增加安全认证和负例。默认 Windows Node Named Pipe 禁止作为安全入口;只有创建时 DACL/SID 已经验证的自定义实现才可选。Grok 原生工具来源、签前参数与时序需先通过 H3-02 最小能力探针,在 Phase 4 NAT-14/C12/S13 正式验收。 diff --git a/docs/interactive-trusted-host-security-v2-review.md b/docs/interactive-trusted-host-security-v2-review.md new file mode 100644 index 0000000..e00c73b --- /dev/null +++ b/docs/interactive-trusted-host-security-v2-review.md @@ -0,0 +1,163 @@ +# FlowKit Interactive — Trusted Host V2 阶段 2 定向安全复审记录 + +**2026-11-11;性质:Grok Build 独立审查者已完成三轮定向复核。** 本文同时记录作者侧的源码/规范交叉核验;不将作者自审冒充外部审查,也不将 Grok 模型复审冒充第三方专业安全认证。Phase 2 整体仍为 CONDITIONAL,F-02/F-04/F-07 的后续门禁未关闭。 + +**固定对照源码:** `main@9bac8f86347a405efe068f96423ae3e501005061`。**审查对象:** 本分支三份 Draft 设计文件。 + +## 1. 源码及产品事实交叉核对 + +| 事实/限制 | 直接证据 | 结论 | +|---|---|---| +| Core 不提供 Agent Provider 客户端,Host 管理 Coordinator | `src/interactive/coordinator.mjs` | 不引入第二 Runtime | +| M5 默认 Host-only signer 和独立数据披露 | `src/interactive/trusted-host.mjs` / `docs/interactive-host-security.md` | 保留 v1 签名契约 | +| v1 statement 有 `proofId`、`receiptHash` 及 Run/Program/Policy identity | `src/interactive/host-attestation.mjs` | 以 Host-only proofId 外部证据索引实现来源绑定,不新增签名字段 | +| M3 Store 按 namespace 隔离,WAL/FULL、transactional CAS | `src/interactive/sqlite-store.mjs` | 不重做 N5;需独立 OS 文件权限 | +| 终态 Host frame 包含完整 State | `src/interactive/coordinator.mjs` | 模型公共结果不能直接使用 Host frame | +| M6 scripted worker 与原生模型不是同一证据 | `tests/integration/m6-worker.mjs` 和 Grok 验收报告 | CI 不能宣称原生 C12/S13 PASS | +| Linux nobody 隔离已有真实脚本证明 | `tests/security/host-isolation.mjs` | Windows ACL / 真实 Grok 仍需补证据 | +| Windows Named Pipe 有默认安全描述符风险 | 微软 CreateNamedPipeW/Named Pipe Security 官方文档 | 优先跨平台 loopback mTLS;Pipe 只作条件替代 | +| Grok Build headless 有结构化工具事件 | xAI Grok Build streaming-json 官方文档 | 需宿主独立观测,不能把 JSON 的 signature 字段当 Provider 级证明 | + +## 2. 对抗性 Finding 逐项验证 + +| ID | 严重性 | 初始发现 | 修订动作 | 当前状态 | +|---|---|---|---|---| +| DR-01 | P1(设计阶段) | 如果让 MODEL_USER 的工具持有 mTLS client key,任何同权限脚本都可冒充受信 Bridge | 增加 §3.2.1 双跳通道:模型仅交候选 JSON,受保护 Bridge 才持 client key,Host 验证独立 `tool_call` 事件 | **设计已关闭;SEC-06/TH-027 待实测** | +| DR-02 | P1(设计阶段) | 若 Host 等待 `submit` 的工具完成事件才签名,而工具等待 Host 结果,会死锁 | §5.3 冻结签名前的 `tool_call` 起始事件+输入摘要关联;签后事件仅用于审计;事件时序不支持时标 BLOCKED 并另审双阶段协议 | **设计已关闭;NAT-14/TH-028 待实测** | +| DR-03 | P1(验收边界) | mTLS、Host 自签 Ed25519 与 Provider 签名三个层次容易被混算 | 定义 P/M/T/N/V 五种证据等级;缺可验证来源不得通过 C12/S13 | **设计已关闭;原生证据待实测** | +| DR-04 | P1(平台安全) | Windows `net.createServer` 没有给出经验证的受控 Pipe DACL/Peer SID | 默认选 Host-owned loopback mTLS;Pipe 必须走独立 Win32 安全说明和负例 | **设计已关闭;Windows 实测待 Phase 3** | +| DR-05 | P1(权限) | 用户的 Grok Build 可能在管理员 Windows session 中运行 | Secure mode 强制非 admin MODEL_USER 和独立 HOST_USER;否则 BLOCKED | **设计已关闭;Windows 身份实测待 Phase 3** | +| DR-06 | P1(签名来源) | Host 只要调用 `createAgentReceiptStatement` 就能签任意 JSON,容易产生认证洗白 | Host-only `proofId→session evidence` 绑定,签名必须后于可验证工具事件,所有不匹配请求零 CAS | **设计已关闭;TH-010/NAT-06 待实测** | +| DR-07 | P1(秘密泄露) | `asPublicFrame` 终态包含完整 State,不可直接转发模型 | Adapter `continuePublic` 返回脱敏 terminal;`readPrivateResult` 只能是 Host/User 控制面 | **设计已关闭;SEC-11 待实测** | +| DR-08 | P2 | Windows Hosted Runner 不能直接继承 Linux UID 证明 | SEC-WIN 独立账户/ACL、Host service control 与真实文件/进程操作负例,缺条件 BLOCKED | **设计已关闭;需专用 Windows 安全测试环境** | +| DR-09 | P2 | CLI `usage.signature` 字段不具备已确认的 Provider 验签契约 | Provider 等级 V 的判断单独进行,任何非正式机制只能提供 HOST_OBSERVED | **设计已关闭;NAT-13 待核验** | +| DR-10 | P2 | 可能把 Human/Action/Parallel 越界引入 P0-A | Bridge v1 仅 Agent result;Human 未有真实渠道时只拒绝并延期 P0-B | **设计已关闭;TH-025 回归** | +| DR-11 | P2 | 只封 DB 主文件,不封 WAL/SHM、日志和备份 | 将 WAL/SHM/证据/backup/Service control/进程句柄列入 OS 负例 | **设计已关闭;SEC-03/04/13 待实测** | +| DR-12 | P2 | Provider 模型调用可能重复,避免误称 exactly-once | 只承诺 CAS 有效状态至多一次;由 Host 处理供应商调用幂等/对账 | **设计已关闭;NAT-08/09 待实测** | + +| DR-13 | P1(持久恢复) | Host 已签回执、尚未接纳就 SIGKILL;签名超期后可能丢失原始证明或误签编造结果 | §6.4 增加 Host-only OBSERVED/SIGNED/ACKED Outbox、签后持久化再 accept、过期未接纳 fail closed、严格原事件重证 | **设计已关闭;TH-029/SEC-18/NAT-15 待实测** | +| DR-14 | P2(容量/隐私) | 原生会话事件和签名 Outbox 可能永久堆积或记录敏感 State | Host-only 审计只保存必要证据与摘要;保留窗口和容量在 Phase 3 配置并测试 | **设计已关闭;TH-030/SEC-19 待实测** | + +| DR-15 | P1(信任边界一致性) | 如果 Bridge 与 Host 同用 HOST_USER,不能同时宣称 Bridge 在 OS 层无权读取 Host signer/SQLite | 明确 Bridge+Host 同权时是一个可信计算基(TCB),只能声明 MODEL_USER 被隔离;需要 Host 对 Bridge 的再隔离时必须使用独立 BRIDGE_USER 及真实 ACL/UID | **设计已关闭;SEC-01/02/05/06 待实测** | + +## 3. 设计冻结所需的可核对不变式 + +- [x] 现有 M5 Ed25519 Statement V1 不变;新增来源证据采用独立 Host-only ledger。 +- [x] Host signer、Coordinator、SQLite、完整 State 不向模型公开。 +- [x] Windows/Linux 身份隔离要求有实际系统权限失败/拒绝证据。 +- [x] Windows 默认 Named Pipe 不会被直接认定为安全。 +- [x] 直接 Grok Build 优先;ACP 不是前置条件。 +- [x] 同权 Developer Mode 只计 P/M,不计 N。 +- [x] 冻结了 tool_call start 与 Host 签名之间的时序;存在反例 NAT-14。 +- [x] 签后、accept CAS 前崩溃和过期回执具备 Host-only Outbox/对账设计及 NAT-15 反例。 +- [x] 30 个 TH Threat、19 个 SEC OS/IPC 用例与 NAT-01..NAT-15 均已列出(NAT-14 为事件时序,NAT-15 为签名 Outbox 恢复)。 +- [x] 对比 P0-A / P0-B / P1 / P2,未在安全设计中偷加 Action/Human/Parallel 能力。 +- [ ] 外部审查者重新核查 Provider/source provenance 能否满足冻结 C12/S13 条件。 +- [ ] Phase 3 的 Windows Host 用户/服务 SID/ACL/mTLS 真实负例 PASS。 +- [ ] Phase 4 Grok CLI 的 native JS Tool loop、`tool_call` 起始事件时序、普通脚本伪造攻击负例 PASS。 + +最后三项是**实施/独立验证门禁**,不是可用文档编写替代的事项。 + +## 4. 对 Stage 0/1 追踪状态的纠正 + +代码层存在的 N1/N3/N5/N7/N8/N9/N10/N11/N12 **不能因为历史设计 Finding 仍在列表里而重写**。它们只需对照冻结需求补足对应负例。N6 跨 SDK 版本兼容仍未实测;N2/N4/N13 由 P0-B 接手。其他 T/S/C 项继续使用完整路线与各自冻结矩阵,当前设计 PR 不会删除或合并它们的状态。 + +## 5. 本轮复审裁决 + +**自审结论:有条件通过设计方向;0 个尚未写出控制措施的新 P0/P1 设计 Finding。** + +**不是外部独立审查通过。** 由于当前执行环境无法代替用户本地的 Windows 服务账户和 Grok Build 会话,Phase 3 的真实安全证明、Phase 4 的原生事件序列均未执行。必须保留 BLOCKED,不得将文档 CI PASS 写成安全验收 PASS。 + +**建议:** 保持文档设计 PR Draft,独立审查时按 DR-01..15、TH-001..030、SEC/NAT 矩阵逐项核对。若没有实质性新设计 Finding,可正式确认本设计并开始 Phase 3;如发现信任域或工具事件顺序不可实现,必须先修正本设计再实施,禁止绕开门禁。 + + +## 6. Grok 独立复审 F-01–F-07 的逐条核验(2026-11-11) + +**外部材料:** `FlowKit-PR14-Trusted-Host-V2-Independent-Security-Review-Grok.md`(对 PR #14 frozen head `d1c7c76d03780f04a5b761699cdbc9ac82f0b86c` 的只读审查,结论 `CONDITIONAL PASS`)。本小节是后续交叉核验,**不是替代 Grok 初审的新第三方意见**。 + +| Finding | 独立交叉核验 | 处理结果及剩余门禁 | +|---|---|---| +| F-01 P1 | **确认。** 旧 §9 同时要求先验证 Grok 工具和把它放到 Phase 4,门禁冲突。 | 主设计 §9.1、路线图 Phase 3 改成唯一入口/退出规则;H3-02 工具能力探针先于通信代码,原生 C12/S13 仍 Blocked。 | +| F-02 P1 | **核心缺口确认,Grok 的“只有 Shell/MCP”和“rawInput 必须逐字节包含全部 normalizedReceipt”不是已证实的硬事实。** 官方 Grok Build 支持通过 MCP 扩展工具;`--tools` 本身仅为内置工具 allowlist。 | 主设计 §5.5 冻结优先 MCP PoC、受信配置及两条摘要:rawInput→toolInputDigest、Host 当前 Pending+参数→receiptHash;在 NAT-14/Grok 实测之前 H3-02 不能投入生产。 | +| F-03 P2 | **确认。** TH-017/023 为 P1,却对齐 SEC-11/04 的 P0。 | 威胁表升级至 P0;TH-028 保留 P1(协议活性而非 P0 越权),但 NAT-14 作为 Phase 4 强制阻断门禁,不得延期放行。 | +| F-04 P2 | **确认机制风险,非跨账户实测。** Windows 句柄继承保留权限;报告只做同用户 fd 探针。 | 主设计、SEC-02/03 增加真正继承句柄表/子进程非授权访问负例;Windows 跨 SID 攻击实测仍 BLOCKED。 | +| F-05 P2 | **官方规则确认,具体 Node SDDL 未独立复现。** 微软说明默认 Named Pipe DACL 给 Everyone/Anonymous 读取,Node 公开选项未提供可指定 SDDL 的安全接口。 | 默认 Node Named Pipe 明确禁止安全 IPC;仅创建时自定义 DACL+SID 的 Win32 引导经验证后可选,或采用受信的本机传输。 | +| F-06 P2 | **确认。** C12 交叉索引缺行、Grok requestId 与 FlowKit requestId 混用风险、Outbox 正文摘要未冻结。 | 验收矩阵补 C12,增加独立 `flowkitRequestId/grokRequestId/grokSessionId/toolCallId`;重签仅对 Outbox 保存的同一 normalizedReceipt canonical bytes/proofId 和当前 Pending 重新核证。 | +| F-07 P2 | **可访问性缺口确认。** 既有会话曾给出 V0.3/V0.6-R5 历史生成路径,但此 PR、当前文件库和工作环境未找到可复核原件。不能推断文件从未存在。 | 从 PR 中移除“已有可核验正式契约”暗示;要求补原文不可变定位和完整 SHA-256 后才可裁决正式契约符合性,当前 BLOCKED。 | + +**额外核验说明**:Grok 本地 Node 默认管道 DACL 与同用户句柄实验没有提供可独立执行的原始脚本/日志;本交叉复审仅采用 Windows 官方文档所证明的权限机制,不冒充已在用户电脑复现。Grok Build MCP 支持来自官方用户指南,但尚未执行 `grok -p` 的 NAT-14 工具时序实测。 + +**当前裁决:** 七项均已登记修订;F-01/03/05/06 的文档矛盾已修正;F-02/04 的设计控制已定义但关键平台实测仍缺;F-07 缺正式原文仍 BLOCKED。PR #14 继续 Draft,**不得以文档 CI 通过替代 Phase 2 的修订段落独立复核,也不得进入 Phase 3 的受信通信实现**。 + +后续:让 Grok Build **只复审本轮修订 diff**、官方 MCP/工具事件时序前置条件与 F-07 原件可访问性;无新实质性设计 Finding 且正式契约可核验后方可关闭 Phase 2。Phase 3/4 的运行证据在其阶段分别取得。 + +- [Microsoft: Named Pipe Security](https://learn.microsoft.com/en-us/windows/win32/ipc/named-pipe-security-and-access-rights) +- [Microsoft: process handle inheritance](https://learn.microsoft.com/en-us/windows/win32/procthread/inheritance) +- [Grok Build: MCP server configuration](https://github.com/xai-org/grok-build/blob/main/crates/codegen/xai-grok-pager/docs/user-guide/07-mcp-servers.md) +- [Grok Build: headless events and `--tools`](https://github.com/xai-org/grok-build/blob/main/crates/codegen/xai-grok-pager/docs/user-guide/14-headless-mode.md) + +## 7. Grok Build 第二轮定向复审与追加闭环 + +**原始报告:** `FlowKit-PR14-Trusted-Host-V2-F01-F07-Targeted-Rereview-Grok.md`;本轮上传文件 SHA-256:`4528278eddb1ade36c8a388c4ad4181f93f8d364a323ca54b0a4c19ea4ee3062`;Grok 核对冻结 HEAD `51a759975abcaee928faf50aec99ebed324fdfcc`,只读裁决 **CONDITIONAL PASS**。本节是事后的针对性代码/文档交叉验证记录,不能冒充 Grok 对新提交的再审 PASS。 + +### 7.1 外部复审裁决(冻结旧 SHA,不能倒填) + +| Finding | Grok 二轮结论 | 独立交叉核对 | 这次修订 | 后续边界 | +|---|---|---|---|---| +| F-01 P1 | PARTIAL | 原 `H3-05→H3-04→H3-03→H3-02`,H3-02 却引用 Phase 4 NAT-14,确有依赖环 | 把 H3-05 移到 H3-01 后、只依赖 H3-01;H3-02 改为独立「工具注册与签前 tool_call 最小能力探针」,**不是 NAT-14**;H3-04 负责集成后全量安全测试,Phase 4 正式 NAT-14 不提前记 PASS | 本次改动需定向 diff 复核,真实 PoC/NAT-14 仍未运行 | +| F-02 P1 | PARTIAL | Grok MCP 工具已具官方扩展机制,但 tool_call.rawInput flush/参数一致性/大值仍未实测 | 维持 §5.5 的候选工具探针与 `toolInputDigest` / `receiptHash` 双哈希规则;没有把 PoC 伪装成成功 | H3-02 实现 BLOCKED,直到可复现小型工具能力探针;C12/S13 仍 BLOCKED | +| F-03 P2 | CLOSED | TH-017/TH-023 与 SEC-11/SEC-04 P0 已对齐 | 不重做 | Phase 3 实际 OS 安全证明未完成 | +| F-04 P2 | PARTIAL | Grok 测到 Node 同用户继承的 fd 可被子进程读取;**没有跨 OS 身份实测** | 保留句柄白名单和跨用户负例 | Phase 3 SEC-02/SEC-03 仍 BLOCKED | +| F-05 P2 | CLOSED | Windows 官方默认 Named Pipe 赋予 Everyone/Anonymous 读取权;报告称 Node 22/24 实测 SDDL,但未提供原始脚本文件 | 保留禁止默认 Node Pipe,安全 Pipe 必须创建时自定义 DACL+SID | SEC-16 仅采用 Named Pipe 时适用,未跑 Win32 实测 | +| F-06 P2 | CLOSED | C12 映射、flowkitRequestId 与 grokRequestId、Outbox canonical bytes 和 receiptHash 规则已存在 | 不重写 Core 或重新序列化签名业务正文 | 真实签后崩溃 SEC-18/NAT-15 未运行 | +| F-07 P2 | NOT_VERIFIABLE | 历史存档存在正式原件的名称与沙箱路径记录,但本次原始字节不可用;不能据此说文件从不存在 | 保留正式契约 V0.3/V0.6-R5 的符合性 **BLOCKED** | 完成符合性裁决仍需正式原文和完整 SHA-256,不得由路线图或审查报告代替 | +| F-R2-01 P2 | 新 Finding | §3.2 说本地端点可选,§7 Profile 与 §10 总结又把 mTLS 当默认,且 SEC-05/07 会暗示必须创建监听器 | §7 Windows/Linux Profile 和最终结论都改为两 OS 身份、Key/DB/句柄保护必选,**mTLS/独立 Bridge/监听端口按实际部署可选**;SEC-05 验证真正的候选入口,SEC-07 无监听时记 N/A—NO_LISTENER 而非 PASS | 本次设计修订需 diff 复核;没有网络端点不能免除模型输入权限验证 | + +### 7.2 单向阶段依赖检查(不得出现旧循环) + +```text +Phase 2 design review + | +H3-01 Host OS identity & secrets isolation + | +H3-05 OS-only security negatives <-- only H3-01; no Grok tool dependency + | | Grok tool capability probe (no NAT-14 PASS) + | | + | H3-02 ingress/tool adapter + | | + | H3-03 evidence/Outbox + | | + +-----------------------------------H3-04 signer + integration security checks + | + Phase 3 OS/IPC security exit (Win + Linux) + | + Phase 4 native Grok, formal NAT-14/S13/C12 +``` + +**范围纪律:** 本次仅文档修订,没有触碰 Program ABI、Ed25519 receipt v1、Coordinator、Store 或其他生产 Core。CI 全绿只证明现有回归没受影响,**不证明**跨用户 Windows ACL、Grok 原生事件时序、Provider 身份或 Phase 3/4 执行完成。 + +**下一步判停:** 本轮 F-01/F-R2-01 的段落修订无新 P0/P1 Finding 后,可认为**这两项设计矛盾**在文档层关闭;但 F-02 的工具能力、F-04 的跨账户隔离和 F-07 的正式契约证据均必须保持原有状态。PR #14 继续 Draft,不因文档回归或作者自审直接合并。 + + + +## 8. Grok Build 第三轮最终定向复核(F-01 / F-R2-01) + +**外部报告:** `FlowKit-PR14-F01-FR2-01-Final-Targeted-Review-Grok.md`,SHA-256 `7936d6cef9d3c26f5870eb2303fe52c6f215487e740c1fa57787e06716c67933`。审查者为前两轮同一 Grok Build 独立审查者;只读核对冻结 HEAD `316e426aa8d96e4a6b6bee8afd35c0cd313fd244`。裁决:F-01、F-R2-01 **CLOSED(设计文档层面)**;不表示 Phase 3/4 安全验收完成。 + +| 复核项 | Grok 最终裁决 | 本项目核验 | 后续状态 | +|---|---|---|---| +| F-01 阶段依赖 | CLOSED | H3-05 仅依赖 H3-01;H3-02 使用独立能力 PoC,不将其冒充 NAT-14;H3-04 负责接入/签名/恢复集成验证;正式 NAT-14 在 Phase 4 | PoC、SEC 与 NAT-14 真实执行仍待后续阶段 | +| F-R2-01 IPC Profile | CLOSED | Secure Windows/Linux 最小 Profile 不强制 mTLS、TCP listener 或独立 Bridge;SEC-05 始终验证真实候选输入路径;SEC-07 仅监听型 TLS/mTLS 存在时强制 | Windows/Linux 两个 Profile 仍需真实权限测试 | +| F-02 | PARTIAL | Grok 原生 MCP tool_call 起始事件、rawInput 对照、截断/大输入仍未实测 | H3-02/NAT-14 BLOCKED,直到真实能力探针与后续验收 | +| F-04 | PARTIAL | 继承句柄机制有 Node POC,但没有 Windows 跨 SID/服务 Token 的真实负例 | Phase 3 SEC-02/03 BLOCKED | +| F-07 | NOT_VERIFIABLE | 正式 V0.3/V0.6-R5 原文和完整 SHA-256 未获得 | 正式契约符合性继续 BLOCKED | + +**本轮额外文档对齐:** Grok 指出 Windows 检查表中“无证书访问 loopback”和“受保护 Bridge client 合法访问”两步未明确限定部署条件。虽然 SEC-05/SEC-07 与 §9.1 已经规定无监听路径,但为避免执行者误解,已把威胁模型第 3 节第 6–7 项改为条件步骤:无监听记录 `N/A—NO_LISTENER` 并验证 SEC-05;无独立 Bridge 记录 `N/A—NO_SEPARATE_BRIDGE` 并验证 SEC-05/06。该修订属于文档一致性收尾,不改变安全要求、不创建新监听端点,也不降低实际候选入口的验证要求。 + +**裁决边界:** 本轮关闭的是 F-01 与 F-R2-01 的设计矛盾。PR #14 仍是 docs-only 设计记录;F-02/F-04/F-07 不得改成 PASS。CI 只证明既有回归,不能证明 Windows Secure Host、Grok 原生来源、C12/S13 或正式契约符合性。是否合并 PR #14 应由用户在确认其作为“带明确 BLOCKED 限制的设计记录”后决定;合并也不自动授权 Phase 3 实施。 + + + +## 9. PR #14 merge gate and remaining limitations + +- The final design review remains documentation-only. GitHub Actions run `43096045021` for HEAD `b9d0c1efe17c386f798e30b4331f7bd90a1936e3` remained queued with zero jobs created for several hours; this is not a PASS or FAIL test result. GitHub Status reported an Actions/Pages/Copilot incident on 2026-11-11 20:48–21:21 UTC, now resolved. The last fully successful regression run is `43045141302` for prior docs-only HEAD `316e426aa8d96e4a6b6bee8afd35c0cd313fd244`. A fresh exact-HEAD PR run is required before the authorized squash merge. No production source changed between those two heads; the intervening changes are documentation only. Do not merge based on a queued run. diff --git a/docs/interactive-trusted-host-security-v2-threat-model.md b/docs/interactive-trusted-host-security-v2-threat-model.md new file mode 100644 index 0000000..6284d45 --- /dev/null +++ b/docs/interactive-trusted-host-security-v2-threat-model.md @@ -0,0 +1,147 @@ +# FlowKit Interactive — Trusted Host V2 威胁模型与攻击面登记(Draft) + +**阶段:Phase 2(设计),2026-11-11。基线:** `main@9bac8f86347a405efe068f96423ae3e501005061`。 +**配套设计:** [Trusted Host V2](./interactive-trusted-host-security-v2-design.md)。 +**状态:** 威胁登记不等于测试通过;验证结果必须引用后续实测的 Git SHA、运行日志和 OS 证据。 + +## 1. 边界、信任主体与“不做”事项 + +| 主体 | 信任级别 | 可做 | 禁止 | +|---|---|---|---| +| MODEL_USER / Grok Build | 不可信模型/普通工具账户 | 查看授权 Public Task;通过受控工具产生结果 | 读取/修改私有 Store、签名密钥、Host 配置、任意 Run 的业务 State | +| Protected Bridge | 已核准受限通信客户端 | 接收仅来自允许的工具会话的数据;发送已鉴别的有限请求 | 任意新建 Run、重写 Program/policy、暴露私有 State、直接签收据 | +| HOST_USER / Host Adapter | 受信执行域 | 审核 Program、Data Disclosure、认证来源、签 receipt、CAS/Journal | 通过模型字符串授权签署、越过原协议伪造状态 | +| Provisioner / Operator | 受信部署主体 | 配置账户、ACL、证书、工件 allowlist、策略 | 作为模型可调用操作暴露这些权限 | +| Provider | 外部服务 | 在其协议范围内提供实际模型回复 | 不假设其一定有可验证会话签名或 exactly-once | +| Admin/root/Kernel | 根信任/明确出界 | 安装/审计 | 已被模型控制则停止宣称隔离 | + +**既有契约:** M5 `createTrustedInteractiveHost()` 是 Host-only API,模型不应获得原始 `complete()`;Host 通过 Ed25519 v1 statement 和签名、Program/Policy Hash、DLP、Store CAS 保障可接受状态。上述机制不能替代底层 OS 权限边界。 + +### 1.1 同 UID/SID 与管理员原则 + +如果 Grok Build 有与 Host 相同的 OS 权限、可进入 Host token,或是本机管理员(可提权修改 ACL、服务及进程),即使程序在两个 Node.js 进程中,安全门禁仍记 `BLOCKED`。Linux 的 `chmod` 与 Windows 的 ACL 不具有直接可比的安全含义。 + +### 1.1.1 Bridge 与 Host 同账户时的 TCB 规则 + +受保护 Bridge 与 Host 若在同一 HOST_USER/UID 下运行,就属于同一个可信计算基(TCB),不能宣称 Bridge 在 OS 层无权访问 Host 私钥或数据库。**最低强制边界是 MODEL_USER 与整个可信 TCB 分离。** 如果还要求在受信 Bridge 被攻破后保护 Host 签名密钥,必须单独部署 BRIDGE_USER 并实测不同账户 ACL/UID。所有模型输入都必须通过严格的工具入口与 Host-side 原生事件观察;Bridge 与 Host 同账户绝不能成为让模型获得任意 Host API 的理由。 + +### 1.2 与阶段对应 + +- Phase 2:规范并审查所有威胁和验证门槛;不声称已运行 Windows/Grok 安全测试。 +- Phase 3:TH-001–TH-017、TH-022–TH-025、TH-027、TH-029、TH-030 的适用 OS/IPC/签名/Human 负例;TH-025 在 P0-A 仅验证伪造 Human 请求被拒绝,真实 Human 审批延后 P0-B。 +- Phase 4:TH-018–TH-021、TH-026、TH-028 的真实 Grok 来源绑定、原生 JS 工具调用以及时序/PID 重放负例。 +- Phase 5/6:复核所有攻击族及 C08/C12/C22/C23 证据。 +- P0-B Human 和 P1/P2 并行新增威胁在相应阶段扩展,不在当前 P0-A 偷做。 + +## 2. 可复现攻击矩阵 + +| ID / 级别 | 攻击 / 风险 | 防护或控制 | 必须出现的负例与通过标准 | +|---|---|---|---| +| TH-001 / P0 | 模型/工具可使用 Host 同一 OS 用户令牌,绕过一切文件目录约定 | Host 与 MODEL_USER 分离;实际 OS token / SID / UID 证明 | 同账户/管理员模式标 BLOCKED;受限模型身份不能提权到 Host | +| TH-002 / P0 | 模型读取 Ed25519 签名私钥或 KMS 授权 | Host-only key custody、ACL、最小进程权限 | MODEL_USER 的真正读取/复制/列目录失败,且其进程不存在可读私钥/Host token 的继承句柄;Host 自身签名 PASS | +| TH-003 / P0 | 模型直接读写 SQLite 主文件 | Host-only DB owner/DACL | 读取、覆盖、CREATE、DELETE、RENAME、替换文件失败;进程句柄表无继承的主库/WAL/SHM/备份文件句柄 | +| TH-004 / P0 | 直接读写 SQLite `-wal`、`-shm`、备份、快照、导出日志 | 与主 DB 同级别的保护;禁止不安全备份 | 主 DB 被拒绝但 WAL/SHM 可读时 FAIL;Host 恢复正常 | +| TH-005 / P0 | 模型通过写入 Host 配置、artifact allowlist、Program 文件替换合法执行 | Host-only config/artifact manifest、exact hash、immutable verified bytes | 可写配置/产物时 FAIL;非授权 Program、policy drift fail closed | +| TH-006 / P0 | Windows 管道默认 ACL 给多余主体访问、预占/伪造管道名 | 禁止默认 Node Named Pipe 作为安全 IPC;需监听时可用 loopback mTLS,若用 pipe 必须显式 DACL+Peer SID+拒绝远程 | 非授权 SID 无法连接、无法预占、无法充当 Server;失败不能自动降级 | +| TH-007 / P0 | 如果启用 loopback TCP,未授权本地程序访问 Host | TLS/mTLS、绑定回环、明确客户端身份限制,并与 Host 独立工具事件绑定 | 无证书、错证书、错误身份不能调用;非回环连接失败 | +| TH-008 / P0 | 若采用客户端证书/受保护 Bridge,模型工具能读取其凭据或伪造 Bridge 身份 | 受信 Bridge 专用凭据不向 MODEL_USER 泄露;即使模型端持有普通候选连接凭据,也不能据此取得 signer 权限;所有实际候选路径仍需独立工具事件校验 | MODEL_USER 模仿真实活动中的提交接口不能生成已签回执,未启用 Bridge/mTLS 的配置记该项凭据子情形 N/A 而非 PASS | +| TH-009 / P0 | 把普通 JSON、`GROK_SESSION_ID` 或模型声称已批准当来源证明 | Host-only supervisor 观察记录、受信 proofId 和 result digest 关联 | 改 sessionId/proofId/工具日志文件不能让 Host 发签名 | +| TH-010 / P0 | Host 给未验证的 response.json / 模型失败文本签署 Ed25519 | 观察证据验证先于 signer | 无工具/来源证据,Host 必须拒绝并保持 Pending/Store 不变 | +| TH-011 / P0 | 模型绕过 Host 安全入口直接调用 `complete()`、SQLite、signer | Coordinator & signer 只在 HOST_USER 运行,所有实际模型候选入口均实施 method allowlist 与权限隔离,不要求额外部署 Bridge 进程 | 任何 model API 都无法获得低层 Host 对象或密钥;未授权方法必拒绝 | +| TH-012 / P0 | 模型触发 `start` 并给自己加入任意 Program artifact allowlist | 可信 provisioning/build manifest、预授权 Run scope | 模型自报 Hash 和初始 State 不能开始未经授权 Run | +| TH-013 / P0 | 错租户、错 Run、错 Node、错 requestId/attempt、旧 Pending 重放 | Host 从当前 Store 重新取 Pending,namespace-bound auth | 所有错身份请求无 CAS/Journal/receipt mutation | +| TH-014 / P0 | 有效签名/旧响应被替换或被其他 Run 复用 | v1 statement binds namespace/run/request/node/attempt/receiptHash/artifact/policy | 改任一字段,验证失败;相同合法重复回执只返回原 Ack | +| TH-015 / P0 | Checkpoint 尚未提交就发送下一个任务;Host 被杀后重复提交 | Store CAS 和先持久再派发;支持 same Run recovery | Publish/Accept/Commit 多切点 SIGKILL 后 Pending identity、State、Journal 一致 | +| TH-016 / P1 | 长输出、恶意 JSON、百万级对象造成内存/CPU/日志拒绝服务 | 有界 transport frame、限流、deadline、canonical receipt v1 2MiB | 上限+1、恶意 key、无效 UTF-8/JSON、重复/超时拒绝;不得篡改 State | +| TH-017 / P0 | 敏感 State/指令出现在 Pending、TLS 返回、Tool 结果或日志 | getPublicAgentTask allowlist + authorizeDisclosure + Host-only private view | canary 不得出现在模型可读流/日志;Host 内部仍保留完整 State | +| TH-018 / P0 | 原生 Grok CLI 输出流或 tool_call 由模型/脚本伪造或替换 | 受信 Supervisor 捕获真实 CLI 事件、安装路径/hash 固定,禁止模型写原始证据目录 | 用 echo/伪造 `tool_call` JSON/改本地日志不能认证为真实工具调用 | +| TH-019 / P0 | 客户端证书只证明 Bridge 账户,却被错当模型 Provider 身份 | `HOST_OBSERVED` 与 `PROVIDER_VERIFIED` 分开;独立原生事件证据 | 单独 mTLS PASS 不得让 C12/S13 获得 PASS;证明会话实际工具调用路径 | +| TH-020 / P1 | 真实模型中途崩溃、Provider 请求重复计费,Host 宣称 exactly-once | 固定 Pending/RequestId、对账、历史 Ack;外部调用按 at-least-once 风险处理 | 接受重复模型调用可能发生;只承诺一次有效 State commit | +| TH-021 / P0 | 工具/会话和 receipt 数据错配(结果 A 冒充结果 B) | 独立 ToolCallId/RequestId/TaskDigest/ResultDigest 绑定,Host-only proofId | 交换两次同 Run 不同 Pending 的结果或工具事件必须拒绝 | +| TH-022 / P1 | Host 签名证据过期、密钥轮换/策略漂移导致在途 Run 无出口 | 固定 policyHash、已核实历史 Ack、轮换排空或显式迁移 | 不制造新旧身份混合回执;旧 Host 可以审计/安全处置 | +| TH-023 / P0 | Windows service 控制权限、进程句柄、debug 权限让 MODEL_USER 以 Host 权限执行代码 | 专用服务 SID、SCM DACL、受限 Token、保护可执行路径 | MODEL_USER 不能修改/重启服务为任意程序,不能 attach/debug/dump Host | +| TH-024 / P1 | 路径重解析、符号链接、硬链接或 TOCTOU 替换 Host 文件 | Host owned path、真实路径/文件句柄验证、不跟随不安全链接 | 重定向私钥/SQLite/Program 读取失败或保持原已验证字节 | +| TH-025 / P0 | 模型构造 `kind:'human'` 或“人工已同意”让流程越权 | P0-A signed receipt 只接受 Agent;P0-B 必须另证 humanProvenance | P0-A `kind:'human'` 直接拒绝;Human 未实施不能表示审批通过 | +| TH-026 / P1 | 捕获会话 PID 后复用同 PID 或人为重放事件 | 进程启动时间/可执行文件摘要/session/tool sequence/host-only nonce | 旧 PID/session/toolCallId 不被新的 Run 自动承认 | + +| TH-027 / P0 | 仅在采用受保护 Bridge/mTLS 时,Bridge 凭据有效却从任意模型 JSON 直接触发转发 | Bridge 仍须依赖 Host-only CLI 工具事件证据;单 Host 进程无 Bridge 时由实际候选数据入口执行同等级校验 | 无可匹配 tool_call 的普通模型工具命令不能触发签名/CAS;没有 Bridge/mTLS 时相关凭据测试记 N/A,但签名前来源验证不能跳过 | +| TH-028 / P1(Phase 4 强制阻断) | Host 等待 submit 的 tool_call_update,submit 又等待 Host 接纳,造成死锁 | H3-02 编码前做**能力探针**验证 tool_call start/input 能签前观察;Phase 4 的正式 NAT-14 仍独立执行;update 作签后审计 | 探针不成立则 H3-02 BLOCKED,但 H3-01/H3-05 OS 测试可先行;正式 NAT-14 未通过则 Phase 4/C12/S13 BLOCKED,不得把 PoC 充当 PASS | + +| TH-029 / P0 | Host 签署 v1 receipt 后、CAS 接纳前崩溃;证明过期后错误重签伪造历史回复 | Host-only OBSERVED/SIGNED/ACKED Outbox,签名后持久化再 accept,恢复时与 receipt-index 对账;过期未接纳时 fail closed | SIGKILL 签名前/签后/CAS 后;未接纳过期证明不得产生状态修改;原有效结果只能经受信证据对账 | +| TH-030 / P1 | 模型结果和 Host 观察日志无限增长或泄漏原始 State/密钥,隐私与磁盘 DoS | Host-only 有界 retention、加密/ACL、按 Run 生命周期和审计窗口清理,避免记录完整敏感文本 | 大量 Run/长链后空间有界;Public Task 和公开日志无 canary;保留必要 hash-chain audit | + +- TH-023/TH-017 是 Phase 3 P0,服务账户可执行权限和敏感 State 误披露不得以 P1 延后;TH-028 虽属协议 P1,但 H3-02 与 Phase 4 的准入条件强制检验工具事件时序,无证据仍为 BLOCKED。 + +**验收证明强度**: +- “模型说无法访问”不是 TH-001–TH-005 证明,必须真的运行拒绝访问的文件/进程命令; +- Linux scripted nobody PASS 不能替代 Windows ACL;Windows 命令直接在不支持平台异常退出时保持 BLOCKED; +- 模型日志中普通 `usage.signature` 字段没有验证算法/密钥/覆盖字段,则不能升格为 `PROVIDER_VERIFIED`; +- 只有通过了原始 JS tool-call 证据、Host 可信接纳、OS 隔离的闭环,才可申请 C12/S13 的 N 层裁决。 + +## 3. Windows 身份及 ACL 防护检查表 + +所有测试必须使用正确的真实 OS Token 执行,而非在同一管理员终端中更改逻辑变量: + +1. 查询 Host、Bridge、Grok CLI 的账户 SID、完整用户组和提升状态; +2. 查询 Host 私有根目录、Key、DB 主/WAL/SHM、Program manifest、可执行文件、日志的 DACL 与 Owner; +3. 验证 Host 服务对象的控制/更改配置权限不能被 Grok 用户调用; +4. 从 Grok 子进程尝试列目录、读、写、改名、替换、删除 Host 私有文件; +5. 从 Grok 子进程尝试打开 Host PID/进程句柄进行敏感权限操作; +6. **仅当部署实际启用 loopback TLS/mTLS 监听端点时**,从 Grok 子进程尝试无证书/伪证书连接;若未启用,记录 `N/A—NO_LISTENER`,不得为了该项创建监听器,并转而验证实际候选数据入口(SEC-05); +7. **仅当部署独立受保护 Bridge client 时**,用该客户端完成合法请求;若采用单一 HOST_USER TCB/无独立 Bridge,记录 `N/A—NO_SEPARATE_BRIDGE`,并验证实际 Host TCB 候选入口和工具事件绑定(SEC-05/06); +8. 证明新进程重启后仍保持隔离; +9. 所有记录脱敏,不把私钥、私有数据库原文上传 CI; +10. 若使用 Named Pipe,检查 SECURITY_ATTRIBUTES/DACL、非授权 SID 连接和服务 SID 验证;默认 Pipe ACL 不构成通过证据。 + +**工具参考**:`whoami /groups`、`whoami /priv`、`Get-Acl`、`icacls`、`Get-LocalUser`、Windows Service Control Manager 的安全描述符检查。实际测试命令在 Phase 3 写入自动化脚本并验证每个断言,不在这里假定其结果。 + +## 4. Linux UID/GID 防护检查表 + +1. `id` / `stat` / `ls -l` 验证 Host 与 Model 不同 UID/GID; +2. Host 私有根 `0700`、密钥 `0600`,包括 WAL/SHM/backup; +3. MODEL_UID 对私有目录全部 read/write/rename/traverse 失败; +4. MODEl_UID 对 `/proc//environ`、FD、ptrace 和 Host PID 访问失败; +5. 真实 Grok Build CLI 在 MODEL_UID 下运行,观察证据由另一 Host UID 收集; +6. 如果采用 UDS,Socket path ACL/group/peer creds 必须复核; +7. 运行已经存在的 `tests/security/host-isolation.mjs` 作为最小回归,但不能把它当成真实 Grok 原生证明。 + +## 5. 安全 Finding 记录与关闭流程 + +每个实测攻击项至少包含: + +```json +{ + "threatId": "TH-003", + "testId": "SEC-WIN-DB-DENY", + "baselineCommit": "", + "os": "windows-2025", + "nodeVersion": "24.22.1", + "hostPrincipal": "", + "modelPrincipal": "", + "inputDigest": "sha256:...", + "observed": "Access denied on read / write / replace", + "hostStillFunctional": true, + "result": "PASS", + "rawEvidenceRef": "" +} +``` + +关闭条件: +- 所有 P0 威胁通过可复现正反例;否则本阶段/宿主 `BLOCKED`。 +- 对 P1 项若尚无运行条件,明确阻断原因、责任域、目标阶段与 re-entry gate;不得忽略。 +- 任何对编译语义、M5 收据 v1、Program ABI 的新修改需要新契约与专门独立审查。 +- 不因单一“安全扫描绿灯”替代负面 OS 访问测试。 +- 建议的判停标准是“冻结攻击用例跑通且 P0/P1 结论可审计”,不是无限制的想象式 Finding 轮次。 + +## 6. 一致性参考 + +- [Existing M5 security contract](./interactive-host-security.md) +- [Proposed design](./interactive-trusted-host-security-v2-design.md) +- [Microsoft Windows pipe ACL](https://learn.microsoft.com/en-us/windows/win32/ipc/named-pipe-security-and-access-rights) +- [Microsoft Windows file ACL/icacls](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/icacls) +- [Microsoft Process Security and Access Rights](https://learn.microsoft.com/en-us/windows/win32/procthread/process-security-and-access-rights) +- [Linux scripted Host isolation](../tests/security/host-isolation.mjs) + +--- + +**状态:威胁已登记,Phase 3/4 真实 OS / CLI 攻击测试尚未执行。** 所有测试入口不得声称现有 Grok Build Windows 同权实验已通过原生安全验收。