Skip to content

Commit 15c12c5

Browse files
committed
feat(sandbox): establish isolation S0 contracts
1 parent c3b00fc commit 15c12c5

23 files changed

Lines changed: 3454 additions & 520 deletions

docs/architecture/SANDBOX_TECH_SELECTION.md

Lines changed: 156 additions & 169 deletions
Large diffs are not rendered by default.

docs/planning/SANDBOX_IMPLEMENTATION_PLAN.md

Lines changed: 222 additions & 266 deletions
Large diffs are not rendered by default.

docs/planning/rich-content-delivery/00-overall-implementation-plan.md

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
> **用途:** 定义聊天富内容能力的目标架构、实施顺序、边界和验收标准。
44
> **受众:** 产品、架构、全栈开发和安全维护者。
5-
> **最后审阅 / Last reviewed:** 2026-08-09
6-
> **状态:** R0–R4 已实现并通过远程 CI;R5R6 仍作为后续计划。本文件保留总体基线与验收方向。
5+
> **最后审阅 / Last reviewed:** 2026-08-13
6+
> **状态:** R0–R4 已实现并通过远程 CI;R5/R6 的执行隔离前置 S0 合同已实现,R5 producer integration、真实 Provider 与 R6 发布 Gate 仍待后续阶段。本文件保留总体基线与验收方向。
77
88
---
99

@@ -52,7 +52,9 @@
5252

5353
### 3.4 把“显示安全”与“执行 Sandbox”分层
5454

55-
受控文件存储、WebView URI 范围、CSP、内容 schema 和解析资源限制是本功能必需的 **内容安全面**。完整 OS Sandbox 是执行面:当 Agent、Skill 或 MCP 运行外部命令、复杂转换器或不可信二进制时,后续必须接入现有 `SandboxBroker`。二者不能互相替代。
55+
受控文件存储、WebView URI 范围、CSP、内容 schema 和解析资源限制是本功能必需的 **内容安全面**。执行隔离是另一层:当 Agent、Skill 或 MCP 运行外部命令、复杂转换器、不可信原生 parser 或受控网络获取时,必须进入 Rust `Execution Isolation Broker`(沿用 `SandboxBroker` 名称)。strict 的共同语义是 snapshot 交付、受验证 manifest/artifact 回收、默认断网、最小环境、进程回收与 capability evidence,而不是要求三平台使用同一种 OS API。二者不能互相替代。
56+
57+
[2026-08 Sandbox 方案复核](../../research/SANDBOX_STRATEGY_REASSESSMENT_2026-08.md) 已于 2026-08-13 纳入仍为 Proposed 的 Sandbox ADR;S0 provider-neutral 合同、snapshot/result 校验与 FakeProvider 测试已落地。任何真实 Provider 进入生产前仍须通过对应 Spike Gate,当前没有可发布 strict Provider。
5658

5759
## 4. 目标架构
5860

@@ -76,20 +78,24 @@ flowchart LR
7678
PREVIEW --> URI["Scoped artifact URI / read command"]
7779
IMAGE --> URI
7880
ARTIFACTS --> EXPORT["Dialog save + Rust copy"]
79-
AGENTEXEC["Agent / Skill external execution"] -. "future, brokered" .-> SANDBOX["SandboxBroker + network policy"]
81+
AGENTEXEC["Agent / Skill / native converter"] -. "structured request" .-> BROKER["Rust Execution Isolation Broker"]
82+
BROKER --> SNAP["Workspace/artifact snapshot"]
83+
SNAP --> PROVIDER["AppContainer / XPC helper / local VM / remote microVM"]
84+
PROVIDER --> RESULT["validated result manifest + artifacts"]
85+
RESULT --> ARTIFACTS
8086
```
8187

8288
## 5. 推荐实施顺序
8389

84-
| 阶段 | 可见交付 | 关键依赖 | 是否阻塞完整 Sandbox |
90+
| 阶段 | 可见交付 | 关键依赖 | 执行隔离依赖 |
8591
|---|---|---|---|
8692
| R0 | 统一 DTO、Schema、迁移、feature flag、安全测试基线 | 现有聊天回归测试 ||
8793
| R1 | 文件/图片产物的可靠保存、展示元数据、下载 | ArtifactService、窄 IPC/URI ||
88-
| R2 | PDF、文本、表格等本地预览与失败回退 | 解析器 Strategy、资源限制 | 否;高风险转换器后接 Sandbox |
94+
| R2 | PDF、文本、表格等本地预览与失败回退 | 解析器 Strategy、资源限制 | 浏览器 parser 否;原生 helper/converter 必须通过已验证执行位置 |
8995
| R3 | 受限图表块、数据表替代、导出 | Renderer Registry、ECharts adapter ||
90-
| R4 | 静态 GeoJSON 地图;受控瓦片试点 | Map renderer、地图数据策略 | 否;远程瓦片需网络/CSP policy |
91-
| R5 | Sidecar/Agent/MCP 规范化产出、权限与审计 | Phase 4 对话迁移、MCP loop | 部分依赖现有 Sandbox 计划 |
92-
| R6 | 安全加固、跨平台验证、清理和发布 | R0–R5、Sandbox 平台能力 | 是,涉及外部执行时 |
96+
| R4 | 静态 GeoJSON 地图;受控瓦片试点 | Map renderer、地图数据策略 | R4a 否;R4b 必须通过 remote 或已验证的 brokered network |
97+
| R5 | Sidecar/Agent/MCP 规范化产出、权限与审计 | Phase 4 对话迁移、MCP loop、ExecutionPlan contract | 非执行 adapter 可先做;外部执行依赖修订后的 provider gate |
98+
| R6 | 安全加固、跨平台验证、清理和发布 | R0–R5、provider capability evidence | 是,涉及外部执行/受控网络的路径按 evidence 分别放行 |
9399

94100
详细工作包与退出条件在 [01-phased-module-practice-plan.md](./01-phased-module-practice-plan.md)
95101

@@ -106,11 +112,13 @@ flowchart LR
106112

107113
### 6.2 是否需要 Sandbox
108114

109-
不需要把完整 OS Sandbox 作为上述静态展示的上线门槛;它不能解决 HTML/XSS、错误 MIME、解压炸弹或 WebView 权限问题。需要在计划中新增以下衔接
115+
不需要把完整执行隔离作为上述静态展示的上线门槛;它不能解决 HTML/XSS、错误 MIME、解压炸弹或 WebView 权限问题。需要在计划中采用以下衔接
110116

111117
- R0 建立 `ContentSafetyPolicy`,包含文件大小、类型、解析时间/页数、像素、嵌套压缩和 URI 授权。
112-
- R2 对 CPU/内存密集或原生二进制转换器采用独立受限 worker;在 Sandbox Provider 可用前,不可用时应拒绝预览并保留下载。
113-
- R5/R6 将 Agent/Skill/MCP 的外部生成过程接入 `SandboxBroker`;网络地图瓦片走受控 provider/broker,不让 WebView 任意直连。
118+
- R2 的 PDF.js/SheetJS/DOCX 文本提取等纯浏览器 parser 可继续使用 worker + 内容配额;原生 helper/converter 必须通过隔离执行。Windows 优先验证无账户 AppContainer 离线 provider;macOS 项目自带窄 helper 使用 App Sandbox + XPC;通用命令或不兼容工具转 remote microVM。provider 不可用时拒绝预览并保留下载。
119+
- R4b 的瓦片、地理编码和第三方生成服务默认通过 remote provider 或已通过攻击测试的 brokered network 获取,再以受管 artifact/custom URI 交付;不得给 WebView 开放任意 `https:`
120+
- R5/R6 将 Agent/Skill/MCP 的外部生成过程接入 Broker:strict 默认复制允许范围为 snapshot,排除 `.git``.misakax``.codex``.agents` 与凭据;结果以受限 manifest/artifact 返回,经 Rust 校验和用户确认后才允许写回真实工作区。
121+
- `host_direct` 仅作为每次显式批准的 full-access 逃生口,必须标明无 OS Sandbox 保证;provider 错误、缺失、区域不符或实验 API 不可用时不得自动选中。
114122

115123
完整矩阵与理由见 [05-filesystem-and-sandbox-research.md](./05-filesystem-and-sandbox-research.md)
116124

@@ -122,16 +130,18 @@ flowchart LR
122130
4. 图表和地图只渲染结构化数据;模型输出的脚本、远程 iframe、任意 tile URL 和内联 SVG 不能执行。
123131
5. 每个图表提供可访问摘要和表格数据;地图提供要素列表/坐标文本;所有操作可键盘触达。
124132
6. 大文件、未知 MIME、损坏文件、解析超时、磁盘不足、过期引用均以可理解的本地化错误降级,不导致会话丢失或崩溃。
125-
7. Agent/MCP 产物的来源、用户导出和策略拒绝均进入结构化审计;涉及外部程序时符合既有 Sandbox 策略
133+
7. Agent/MCP 产物的来源、用户导出和策略拒绝均进入结构化审计;涉及外部程序时记录执行位置、snapshot 摘要、网络模式、实际 isolation evidence 与结果 manifest,且无隐式 host-direct fallback
126134

127135
## 8. 风险与非目标
128136

129137
| 风险 | 策略 |
130138
|---|---|
131139
| 模型返回伪造/恶意结构 | 只接收工具/adapter 产出的 schema;Rust 再验证;未知块 fail closed |
132140
| Base64/大 JSON 使 SQLite、导出和滚动变慢 | 二进制离库;块/预览懒加载;内容哈希去重与配额 |
133-
| 文件解析器遭遇畸形文件或资源耗尽 | 类型 allowlist、魔数检测、页/行/像素/时间上限;必要时 worker + Sandbox |
134-
| 地图瓦片带来隐私、密钥和 CSP 扩张 | 静态 GeoJSON 优先;受控 tile source、Rust broker、缓存和 attribution |
141+
| 文件解析器遭遇畸形文件或资源耗尽 | 类型 allowlist、魔数检测、页/行/像素/时间上限;浏览器 worker 资源不可保证时仅下载,原生 helper 使用已验证隔离位置 |
142+
| 地图瓦片带来隐私、密钥和 CSP 扩张 | 静态 GeoJSON 优先;受控 tile source、remote/verified network broker、artifact 缓存和 attribution |
143+
| provider 能力或平台实现不对称 |`IsolationEvidence` 和兼容矩阵决定是否可用;不以“已编译”或统一 provider 名称代替安全保证 |
144+
| snapshot 复制和写回发生冲突 | 绑定 base generation;限制文件数/大小/删除范围;Rust 验证 manifest,用户查看 diff 后显式 apply |
135145
| 组件注册表沦为散乱 if/else | 明确渲染器端口、能力声明、契约测试与 feature flag |
136146
| 直接修改既有 `content` 造成历史损坏 | 新表/dual-read/dual-write,迁移完成后再切换读路径 |
137147

@@ -143,4 +153,4 @@ flowchart LR
143153

144154
开始 R4 前必须确认:是否有合法的地图数据/瓦片服务、隐私提示、attribution、缓存上限和在线/离线行为。
145155

146-
开始 R5 前必须确认Sidecar 已从 501 占位迁移至真实对话链路;外部执行是否已满足 Sandbox Provider 的对应平台 gate
156+
开始 R5 的非执行 adapter 前必须确认 Sidecar 已从 501 占位迁移至真实对话链路。启用任何外部执行前还必须确认:已实现的 S0 immutable `ExecutionPlan`、snapshot/result manifest、`ExecutionLocation``WorkspaceDelivery``NetworkMode``IsolationEvidence``ProviderAvailability` contract 已完成 S0.5 事务写回/审批/持久审计;目标 Provider 已通过对应 Windows/Linux/macOS/Remote Spike Gate。默认启用或企业发布还必须通过 S4 的区域、镜像、密钥代理、运维与独立安全评审。否则该执行路径保持 disabled + diagnostic

docs/planning/rich-content-delivery/01-phased-module-practice-plan.md

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
> **用途:** 将总体方案拆为可独立验收、可回滚的实施工作包。
44
> **受众:** 实施开发者、测试和 AI Coding Agent。
5-
> **最后审阅 / Last reviewed:** 2026-08-09
6-
> **状态:** R0–R4 已按阶段门禁完成;R5、R6 保持后续规划。实现和 CI 证据见 [实施过程记录](./06-implementation-log.md)[R0–R4 交接](./09-r0-r4-handoff.md)
5+
> **最后审阅 / Last reviewed:** 2026-08-13
6+
> **状态:** R0–R4 已按阶段门禁完成;R5/R6 的执行隔离前置 S0 合同已实现,R5 producer integration 与 R6 发布 Gate 保持后续规划。实现和 CI 证据见 [实施过程记录](./06-implementation-log.md)[R0–R4 交接](./09-r0-r4-handoff.md)
77
88
---
99

@@ -13,6 +13,7 @@
1313
- 任何数据库迁移必须向前兼容:旧 `messages.content` 仍可读,导入/导出在过渡期不得静默丢失块或附件。
1414
- `artifact_id` 是唯一跨层引用;前端、模型、工具和 URI 不传宿主绝对路径。
1515
- 所有二进制、解析、下载、预览均通过 Rust application service;React 只请求 metadata、一次性预览 URL 或显式 download/export command。
16+
- 涉及外部进程、原生不可信 helper 或受控联网时,Rust `Execution Isolation Broker` 是唯一执行入口;strict 默认使用 snapshot,不直接挂载/写入真实工作区,且 provider 不可用时 fail closed。
1617
- 每一个新事件携带 `message_id``block_id``generation`/`revision`;前端丢弃已重生成、已删除或不属于当前会话的迟到事件。
1718
- 每个阶段完成后先通过代码审查和全部相关本地测试,再更新 [实施过程记录](./06-implementation-log.md)、提交并非强制推送当前阶段;只有远程仓库 required CI 全绿且所需 reviewer 已批准,才能启动下一阶段。完整门禁见 [AI Coding 执行说明 §7](./07-ai-coding-execution-guide.md#7-阶段完成门禁代码审查本地验证git-与远程-ci)
1819
- 涉及 UI 时同步项目 `docs/design/` 规范;远程 CI 失败或不可查询时,当前阶段保持未完成,按执行说明处理。
@@ -90,8 +91,9 @@
9091
1. 定义 `Previewer` Strategy:`canPreview(metadata)``prepare(artifact)``getViewModel()``dispose()`;注册表按 MIME + magic bytes 选择,而非后缀。
9192
2. 预览任务与主聊天列表分离:点击后懒加载,显示可取消进度;取消/离开会话时中止并释放对象 URL/worker。
9293
3. 对 CSV/XLSX/DOCX/PDF 应用页数、行列、解压、时间、内存与并发限制;输出只保留受限 preview derivative,不保存任意解析脚本。
93-
4. R2 初期禁用 HTML、SVG、Office 宏、嵌入对象、任意 iframe 和远端图片;若未来支持,必须先完成独立 renderer sandbox 设计评审
94+
4. R2 初期禁用 HTML、SVG、Office 宏、嵌入对象、任意 iframe 和远端图片;若未来支持,必须先完成独立 renderer 安全设计评审。iframe sandbox 不能作为唯一防线;需要原生解析/转换时还必须进入已验证的执行隔离位置
9495
5. 预览面板可在聊天卡内展开,也可使用受限的二级 `Dialog`;不新建拥有主窗口 capability 的通用远程 webview。
96+
6. 纯浏览器 PDF.js/SheetJS/DOCX 文本解析通常留在受限 worker;若 parser 资源上限无法保证、需要项目自带原生 helper 或调用外部 converter,则分别采用:Windows 已验证 AppContainer offline、macOS App Sandbox + XPC 窄 helper,或 remote microVM。任何 provider 不可用时只保留原件下载。
9597

9698
### 退出门
9799

@@ -131,7 +133,7 @@
131133
1. 定义 `MapSpec v1`:GeoJSON FeatureCollection、marker、bounds、初始视角、只读 label/属性和 attribution;禁止 JS 表达式、任意 HTML popup、`file:` 与模型给出的 tile URL。
132134
2. 实现 `MapRenderer`,动态加载 MapLibre GL JS,并以 WebGL unavailable/地图数据错误/超要素数为可恢复状态。
133135
3. R4a 仅使用本地 GeoJSON + 明确的基础底图策略;保存地图的静态视图/数据导出通过 ArtifactService。
134-
4. R4b 如产品确认在线瓦片,创建 `TileSourceRegistry`(ID、许可、attribution、允许域、密钥来源、缓存与离线策略),请求经 Rust broker/custom URI 代理;不把宽 `https:` 加入主 WebView CSP。
136+
4. R4b 如产品确认在线瓦片,创建 `TileSourceRegistry`(ID、许可、attribution、允许域、密钥来源、缓存与离线策略)。请求由 remote provider 或已经证明 egress 不可绕过的 brokered network 获取,经 ArtifactService/cache 与 custom URI 交付;不把宽 `https:` 加入主 WebView CSP,也不把普通 `HTTP_PROXY` 视为网络隔离
135137
5. 补充坐标文本、要素列表和“复制坐标/导出 GeoJSON”替代交互;定位用户当前位置必须单独征得用户权限,不由模型触发。
136138

137139
### 验收
@@ -152,13 +154,17 @@
152154
2. 为 Agent 提供窄工具:`present_chart``present_map``create_artifact``attach_image`;工具入参是 schema,不能接收 URI、宿主路径、HTML 或代码。
153155
3. 扩展 SSE/Tauri 事件为 block lifecycle:`stream:block_started``stream:block_ready``stream:block_failed`;保留现有 token/thinking/complete 事件兼容。
154156
4. MCP 工具结果先经过 Artifact ingress policy、来源标记和用户权限;未经批准的 MCP 不能直接注册可展示资源。
155-
5. 对需要运行转换器/生成器的 Agent、Skill、MCP 路径接入 `SandboxBroker``workspace-write`/`read-only` policy;未完成的 OS provider 不得自动退回宿主执行。
157+
5. 将需要运行转换器/生成器的 Agent、Skill、MCP 路径接入 Rust `Execution Isolation Broker`。富内容工具仍只接受 schema/artifact ID;执行请求使用独立的结构化 argv contract,不能接收 shell 拼接、平台 profile、VM 参数、网络规则或原始 host path。
158+
6. 为执行合同增加 `ExecutionLocation``WorkspaceDelivery``NetworkMode``IsolationEvidence``ProviderAvailability``host_direct` 显式建模为 full-access,不属于 strict,且只能每次明确批准。
159+
7. strict 执行默认生成工作区/artifact snapshot,排除 `.git``.misakax``.codex``.agents`、凭据和越界符号链接;provider 只返回受限 result manifest 与 artifacts。Rust 校验路径、hash、配额、删除范围和 base generation,用户确认 diff 后才写回真实工作区。
160+
8. provider 策略按场景非对称:Windows 离线任务等待 AppContainer/实验 API Spike;macOS 通用命令优先 remote microVM、可选本地 Linux VM,项目自带窄 parser helper 才使用 App Sandbox + XPC;联网或未知工具优先 remote。Windows 专用账户与 macOS Seatbelt 不作为默认建设路径。
156161

157162
### 退出门
158163

159164
- Rig fallback 与 Sidecar 主链均能生成同一种 canonical block。
160165
- 取消、重生成、MCP 拒绝、Sidecar 重启和流结束异常不会留下孤立 artifact 或错配 block。
161166
- 每个产物可追踪来源(模型/Agent/Skill/MCP/用户)、会话和触发消息。
167+
- 外部执行还必须可追踪执行位置、snapshot 摘要、区域/网络模式、lease、实际 evidence 与结果 manifest;provider 错误稳定返回 `SANDBOX_UNAVAILABLE`,不调用宿主 shell。
162168

163169
## R6:性能、安全加固与发布
164170

@@ -167,7 +173,7 @@
167173
1. 做大小、内存、GPU、地图 tile、PDF 页、XLSX 解压与消息虚拟列表基准;为超限确立产品可见阈值。
168174
2. 三平台验证 custom/asset URI、文件名 Unicode、长路径、保存对话框、WebView2/WebKitGTK、GPU/WebGL 退化和清理任务。
169175
3. 完成安全回归:XSS、恶意 SVG/HTML、路径 traversal/symlink、MIME confusion、zip bomb、URI auth、CSP/capability diff、超时/取消和跨会话访问。
170-
4. 对需要外部执行的 preview/generator,按既有 Sandbox B0–B7 平台 gate 验证;无 strict provider 时明确禁用该可执行路径
176+
4. 对需要外部执行的 preview/generator,先完成 2026-08 复核定义的 S0 合同,再按执行位置通过对应 Gate:remote snapshot 垂直切片(S1)、Windows 无账户 AppContainer(S2)、macOS XPC 窄 helper/本地 VM(S3);默认启用/企业发布另过组织 provider、地区/镜像/密钥代理、运维和独立安全评审(S4)。只按实际 capability evidence 放行;无 strict provider 时禁用该路径
171177
5. 完成保留策略、手动“清理产物”、隐私/地图 attribution 文案、可观测性和 release notes。
172178

173179
## 依赖与并行性
@@ -183,7 +189,11 @@ flowchart LR
183189
R3 --> R6
184190
R4 --> R6
185191
R5 --> R6
186-
SB["Existing Sandbox B0–B5"] -. "external converters / agent execution" .-> R5
192+
S0["Isolation S0\ncontract + snapshot + FakeProvider"] -. "required for execution path" .-> R5
193+
S1["S1 remote snapshot gate"] -. "networked / cross-platform strict" .-> R5
194+
S2["S2 Windows AppContainer gate"] -. "local offline" .-> R6
195+
S3["S3 macOS XPC / VM gate"] -. "native helper / optional local strict" .-> R6
196+
S4["S4 enterprise hardening / default-enable gate"] -. "release evidence" .-> R6
187197
```
188198

189-
R3 和 R4 可以在 R0 完成后并行;R2 必须复用 R1 的存储和授权R5 的非执行部分可先做 adapter/事件,涉及外部进程的部分等待对应 Sandbox gate
199+
R3 和 R4 可以在 R0 完成后并行;R2 必须复用 R1 的存储和授权R5 的非执行 adapter/事件可先做;任何外部进程先依赖已完成的 S0 合同和待完成的 S0.5,随后按实际执行位置依赖 S1/S2/S3,默认启用或企业发布再依赖 S4。Sandbox ADR 与总实施计划已于 2026-08-13 修订;未通过对应门禁的执行路径继续保持 disabled + diagnostic

0 commit comments

Comments
 (0)