背景
沙箱模式(#506)首期在 macOS(Seatbelt)/ Linux(bwrap)落地了 OS 级写围栏,Windows 侧留作后续:UI 禁用沙箱两项并提示"受限令牌方案开发中",执行层 fail-closed。本 issue 跟踪 Windows 端的实现。
目标
在 Windows 上提供免管理员、零配置、fail-closed 的 workspace-write 写围栏,语义与 macOS/Linux 对齐:
- 写入仅限工作区目录 + 临时目录,工作区外写入被拒
- 广读(免管理员无法做读掩蔽,与 macOS/Linux 的敏感目录读 deny 存在能力差异)
- 无需管理员权限、无需额外依赖、开箱即用
- 不可用时报错,绝不静默降级为直跑
技术方案(Option A:自我再执行 launcher)
sandbox.rs windows wrap_command 返回 (current_exe, ["__sandbox_exec", "--write-root", root, "--", program, args...])
windows_sandbox.rs 在 run() 首行(Tauri 初始化前)识别 marker:
- 给工作区盖
(OI)(CI) 继承写 ACE(合成 workspace SID)
- 建
WRITE_RESTRICTED 受限令牌(合成 SID 作 restricting SID ⇒ 广读、写限工作区)
CreateProcessAsUserW 拉起真实 shell,WaitForSingleObject(INFINITE) 后透传退出码
- Job Object
KILL_ON_JOB_CLOSE 兜底;任何失败退 127,绝不直跑
- 安全加固:
lpApplicationName 用 PATH 内绝对路径解析(工作区 cwd 绝不被搜索,挡 planted-binary);ensure_write_ace 跳过 null-DACL;setup_fenced_temp 拒绝 reparse point
能力差异 / 门控
capability() 返回 supported: true, mechanism: "restricted-token", network_control: false
- sandbox 模式在 Windows 放开
- sandboxOffline(断网 + 读掩蔽免管理员做不到)保持 fail-closed 禁用:前端按
network_control 单独禁用该项,执行层对 !allow_network 直接报错兜底(设置可能自 macOS 同步)
关联
🤖 Generated with Claude Code
背景
沙箱模式(#506)首期在 macOS(Seatbelt)/ Linux(bwrap)落地了 OS 级写围栏,Windows 侧留作后续:UI 禁用沙箱两项并提示"受限令牌方案开发中",执行层 fail-closed。本 issue 跟踪 Windows 端的实现。
目标
在 Windows 上提供免管理员、零配置、fail-closed 的 workspace-write 写围栏,语义与 macOS/Linux 对齐:
技术方案(Option A:自我再执行 launcher)
sandbox.rswindowswrap_command返回(current_exe, ["__sandbox_exec", "--write-root", root, "--", program, args...])windows_sandbox.rs在run()首行(Tauri 初始化前)识别 marker:(OI)(CI)继承写 ACE(合成 workspace SID)WRITE_RESTRICTED受限令牌(合成 SID 作 restricting SID ⇒ 广读、写限工作区)CreateProcessAsUserW拉起真实 shell,WaitForSingleObject(INFINITE)后透传退出码KILL_ON_JOB_CLOSE兜底;任何失败退 127,绝不直跑lpApplicationName用 PATH 内绝对路径解析(工作区 cwd 绝不被搜索,挡 planted-binary);ensure_write_ace跳过 null-DACL;setup_fenced_temp拒绝 reparse point能力差异 / 门控
capability()返回supported: true, mechanism: "restricted-token", network_control: falsenetwork_control单独禁用该项,执行层对!allow_network直接报错兜底(设置可能自 macOS 同步)关联
🤖 Generated with Claude Code