Skip to content

feat(sandbox): 对话框内命令执行方式选择器 + OS 级沙箱执行 - #505

Open
coder-hhx wants to merge 6 commits into
mainfrom
feature/rust-embed-cubesandbox
Open

feat(sandbox): 对话框内命令执行方式选择器 + OS 级沙箱执行#505
coder-hhx wants to merge 6 commits into
mainfrom
feature/rust-embed-cubesandbox

Conversation

@coder-hhx

@coder-hhx coder-hhx commented Aug 16, 2026

Copy link
Copy Markdown
Collaborator

Closes #506

概述

新增「命令执行方式」选择器,放在聊天输入栏工具条(推理选择器旁),单一互斥维度四档:

模式 行为
逐条审批 (ask) 非只读工具每次执行前请求用户批准(复用现有审批卡片与会话记住机制)
自动执行 (auto,默认) 按设置中的工具权限策略直接执行——既有行为,零回归
沙箱 (sandbox) Bash / ManagedProcess 在 OS 级沙箱内执行
沙箱·断网 (sandboxOffline) 沙箱基础上进一步禁止命令联网

沙箱实现

新增 src-tauri/src/runtime/sandbox.rs,按平台分后端:

  • macOS:/usr/bin/sandbox-exec + 动态 Seatbelt profile。allow-default + 全盘写 deny + 工作区/临时目录写 allow + 敏感目录读 deny + 工作区 re-allow。规则为"最后命中者优先",工作区 re-allow 必须排在敏感目录 deny 之后(默认工作区在 ~/.liveagent 内),顺序有单测锁定。
  • Linux:bwrap(--ro-bind / / + 工作区可写 bind + tmpfs 掩蔽敏感目录 + 可选 --unshare-net),启动时真实探测可用性(容器/受限内核下 bwrap 可能存在但无法建 namespace)。
  • Windows:暂不支持。选择器中沙箱两项按平台判定禁用并提示"受限令牌方案开发中";即便设置从其他平台同步过来,执行层也会 fail-closed 报错,绝不静默直跑。后续按 Codex 路线(restricted token + Job Object + WFP)单独实现。

掩蔽范围:~/.ssh~/.aws~/.gnupg~/.config/gh~/.liveagent(provider 密钥库所在)。

拦截点:spawn_platform_shell_command 唯一 spawn 漏斗(Bash + ManagedProcess 共用),沙箱包裹发生在 shell candidate 选定后、Command::new 前;包裹失败直接报错。Hook/Cron 脚本是用户显式配置的自动化,不属于模型驱动面,不套沙箱。

配套改动

  • ShellRunResponse 新增 sandbox 字段;Bash 结果头部显示 sandbox: seatbelt,模型与用户都能确认命令在沙箱内执行
  • 沙箱开启时 Bash 工具描述告知模型围栏规则(拦截报 operation not permitted 时不要试 sudo)
  • 新增 system_sandbox_capability 命令 + @liveagent/adapters/sandboxCapability 双端适配(WebUI 返回 null,由桌面端裁决)
  • 设置键 system.commandSafetyMode 字符串枚举:GUI/WebUI settings 双份同步、Rust 归一化 + 保存白名单、i18n 四 block 同加
  • WebUI 远程会话天然生效:执行始终回到桌面端同一漏斗

验证

  • Rust 705 tests ✅(含 Seatbelt profile 顺序断言、bwrap 参数顺序断言)
  • GUI 前端 1632 tests ✅(含 i18n parity)/ WebUI 557 tests ✅
  • tsc 双端 ✅ / biome(改动文件)✅ / check-ui-boundaries ✅
  • macOS 实机冒烟:工作区内写 ✅、区外写被拒 ✅、~/.ssh 读被拒 ✅、断网 curl exit 6 ✅

后续(不在本 PR)

  • Windows 受限令牌后端
  • PTY 终端工具纳入沙箱

🤖 Generated with Claude Code

Screenshots / preview

默认(自动执行) — 输入栏工具条新增命令执行方式选择器:

composer auto mode

下拉菜单 — 四档模式,带图标与说明,Windows 上沙箱两项禁用并提示:

mode dropdown

沙箱模式激活 — pill 转为绿色盾牌,此后 Bash / ManagedProcess 均在 OS 沙箱内执行:

sandbox active

新增命令执行方式(commandSafetyMode),在聊天输入栏工具条切换,单一互斥维度:
- 逐条审批(ask):非只读工具每次执行前都请求批准
- 自动执行(auto,默认):按设置中的工具权限策略直接执行
- 沙箱(sandbox):Bash/ManagedProcess 在 OS 级沙箱内执行
- 沙箱·断网(sandboxOffline):在沙箱基础上禁止命令联网

沙箱实现(runtime/sandbox.rs):
- macOS:/usr/bin/sandbox-exec + 动态 Seatbelt profile(allow-default +
  全盘写 deny + 工作区/临时目录写 allow + 敏感目录读 deny + 工作区 re-allow,
  规则顺序有单测锁定)
- Linux:bwrap(--ro-bind / / + 工作区 bind + tmpfs 掩蔽敏感目录 +
  可选 --unshare-net),带真实可用性探测
- Windows:暂不支持(受限令牌 + Job Object + WFP 路线待实现),选择器中
  沙箱两项禁用并提示,执行层 fail-closed 兜底
- 掩蔽范围:~/.ssh、~/.aws、~/.gnupg、~/.config/gh、~/.liveagent
- 拦截点:spawn_platform_shell_command 唯一漏斗(Bash + ManagedProcess 共用),
  沙箱包裹失败直接报错,绝不静默降级
- Hook/Cron 脚本为用户显式配置的自动化,不套沙箱

配套:
- ShellRunResponse 新增 sandbox 字段,Bash 结果头部显示 sandbox: seatbelt
- Bash 工具描述在沙箱开启时告知模型围栏规则
- system_sandbox_capability 命令 + adapters 探测(WebUI 返回 null 透传)
- 设置持久化(含保存白名单)、GUI/WebUI settings 双份同步、i18n 四 block 同加

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

PR governance checks passed. Awaiting human review.

@StackCairn
StackCairn marked this pull request as draft August 16, 2026 07:40
…besandbox

# Conflicts:
#	crates/agent-gateway/web/src/app/GatewayApp.tsx
#	crates/agent-gateway/web/src/i18n/config.ts
#	crates/agent-gateway/web/src/lib/settings/index.ts
#	crates/agent-gui/src-tauri/src/lib.rs
#	crates/agent-gui/src/i18n/config.ts
#	crates/agent-gui/src/lib/settings/index.ts
#	crates/agent-ui/src/pages/chat/ChatComposerBar.tsx
@coder-hhx
coder-hhx marked this pull request as ready for review August 16, 2026 08:25
@StackCairn
StackCairn marked this pull request as draft August 16, 2026 08:25
@coder-hhx
coder-hhx marked this pull request as ready for review August 16, 2026 08:27
@StackCairn
StackCairn marked this pull request as draft August 16, 2026 08:27
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coder-hhx
coder-hhx marked this pull request as ready for review August 16, 2026 08:40

@su-fen su-fen left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

结论:当前不建议直接合入,建议先 Request changes。

阻塞问题:

  1. P1:远程 WebUI 的安全模式不会生效。 buildGatewaySystemSettings 只发送 executionModeworkdir,没有发送 commandSafetyModecrates/agent-gateway/web/src/app/chatEventUtils.ts:102)。桌面端远程请求类型和桥接逻辑也没有该字段,最终执行仍读取桌面本地的 settings.system.commandSafetyModecrates/agent-gui/src/pages/chat/runtime/useSendChatTurn.ts:1588)。因此 WebUI 选择“沙箱/沙箱·断网”时,远程命令可能仍按 auto 执行,安全语义失效。

  2. P1:工作区根目录可以重新暴露敏感目录。 macOS 先 deny 敏感目录,随后对整个 write_root 做 read/write re-allow(crates/agent-gui/src-tauri/src/runtime/sandbox.rs:175);Linux 先用 --tmpfs 掩蔽,再用 --bind write_root write_root 重新暴露(crates/agent-gui/src-tauri/src/runtime/sandbox.rs:275)。当用户把工作区设为 home 目录甚至 / 时,~/.ssh~/.liveagent 等会重新可读写,沙箱边界被绕过。应拒绝与敏感目录存在祖先/包含关系的工作区,或改为不会重新暴露敏感子目录的挂载/profile 规则。

  3. P1:isolated=true 的 ManagedProcess 生命周期被破坏。 Linux bwrap 始终加入 --die-with-parentcrates/agent-gui/src-tauri/src/runtime/sandbox.rs:255),但现有语义要求 isolated 进程在 LiveAgent 退出后继续运行;调用路径没有根据 isolated 调整沙箱参数(crates/agent-gui/src-tauri/src/runtime/managed_process.rs:525)。应修复生命周期语义并补充 isolated + sandbox 的回归测试。

GitHub CI 检查目前全部通过,但现有 CI 没有实际执行 Linux bwrap 或 macOS Seatbelt 的运行时冒烟测试,建议补充后再合入。

coder-hhx and others added 3 commits August 16, 2026 23:30
…ss lifecycle

Address two P1 review blockers on the sandbox write fence:

P1#2 — Workspace root could re-expose sensitive dirs. The write fence
re-allows write_root last (macOS re-allow rule, Linux --bind after --tmpfs),
so a workspace of $HOME or / would re-open ~/.ssh, ~/.liveagent, etc. Add a
fail-closed validate_workspace() in the shared wrap_command choke point:
reject any workspace that encloses/equals a sensitive dir, and any workspace
nested inside a credential dir (~/.ssh/.aws/.gnupg/.config/gh). The app-config
dir (~/.liveagent) is exempt in the descendant direction so the default
workspace ~/.liveagent/default-project still runs.

P1#3 — isolated ManagedProcess lifecycle was broken on Linux. bwrap always
added --die-with-parent, killing isolated long-lived processes when LiveAgent
exits. Thread an `isolated` flag through SandboxSpec (default false for the
Bash tool path, true for isolated managed processes) and omit
--die-with-parent when set, mirroring the existing conditional --unshare-net.

Adds cross-platform tests for workspace validation and the bwrap flag.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
远端 WebUI / 队列 / 编辑重发的请求经网关下发时,useSendChatTurn 硬编码使用
本地 settings.system.commandSafetyMode,忽略了请求自带的安全模式,导致远端
选定的沙箱模式无法生效。

- proto: ChatRequest 新增 command_safety_mode 字段(regen Go/TS/Rust)
- Go 网关: NormalizeCommandSafetyMode 白名单归一(非法/空→"")并全链路透传
- WebUI: buildGatewaySystemSettings / payload / adapters 补齐字段
- 桌面端: 网关事件 → bridge override → useSendChatTurn 优先级链
  (override ?? 网关直带 ?? 本地设置),fail-closed 回落本地而非默认 auto
- 队列: QueuedChatTurn 顶层携带 commandSafetyMode,保留入队时的安全模式

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…besandbox

# Conflicts:
#	crates/agent-gui/src-tauri/src/commands/runtime/shell.rs
#	crates/agent-gui/src/lib/tools/shellTools.ts
#	crates/agent-gui/src/pages/ChatPage.tsx
#	crates/agent-ui/src/pages/chat/ChatComposerBar.tsx
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] 沙箱模式:命令执行方式选择器 + OS 级沙箱隔离

2 participants