沙箱与权限
Linux(bubblewrap / Landlock)、macOS Seatbelt、Windows ACL runner 的差异,以及 read-only / workspace-write / danger-full-access 三档模式。
qialike 通过 harness 的 ctx.sandbox.confine() 运行受限 bash(Windows 上是 pwsh)。三个平台都开箱即用:
Linux 优先用宿主的 bubblewrap,没有则落到 qialike 自带的 Landlock(需内核启用该 LSM,≥5.13);macOS 用系统自带的 Seatbelt;Windows 用 harness 的 ACL restricted-token runner。danger-full-access 不加隔离直接运行。
沙箱的边界是「与宿主共享内核和文件系统的子进程」。需要隔离整个环境时,应当使用容器、microVM 或远程执行器。
三档模式
在输入框按 Tab 循环切换,状态栏会显示当前档位:
| 模式 | 状态栏标签 | 效果 |
|---|---|---|
read-only | Read Only | 拒绝写入,必需 sink(如 /dev/null)除外。 |
workspace-write | Workspace Write | 允许写入工作区根目录及后端定义的临时区域。 |
danger-full-access | Full access | 绕过隔离;直接 spawn 原始 argv。 |
几点语义:
- 默认是
workspace-write。会话恢复时,档位取自会话最后一条持久化的sandbox/mode事件——也就是你上次的选择,而不是一个新的默认值。 - 档位与审批策略是解耦的。切到
danger-full-access只抬高文件边界,不会顺手把审批策略变成「永不询问」。关闭审批始终是一次显式的人类动作(在审批弹窗里对某个工具选「Allow always」)。 - 被拒绝的调用会带
[sandbox: file access denied under <mode> mode]标记;模型可以用sandbox_permissions(足以放行的最窄更宽模式)加justification重试一次完全相同的调用,由人类审批。升权必须严格宽于当前生效模式,且只作用于该次调用。
Linux:bubblewrap → Landlock 两级
受限 bash 优先经 bwrap(bubblewrap)运行,并要求内核开启非特权 user namespace。装了 bubblewrap 就是这一档,安全性最好:
# Debian / Ubuntusudo apt install bubblewrap
# Fedora / RHELsudo dnf install bubblewrap
# Archsudo pacman -S bubblewrap没有 bubblewrap 不等于没有沙箱:qialike 自带 Landlock 档(apps/tui-bin/src/landlock-shim.ts 实现其 launcher),只要内核启用了 Landlock LSM(≥5.13)就会自动落到这一档,功能上仍受内核级约束。
两级都不可用时才会发生下面这些(这才是 SANDBOX_UNAVAILABLE 的触发条件):
- 应用照常启动。
- 非 shell 工具全部可用(纯 JS 的
fs-sandbox栅栏仍在)。 - 但
workspace-write/read-only下每条 bash 都 fail-closed 报SANDBOX_UNAVAILABLE,而不是不受限制地运行。 - 只有
danger-full-access(无隔离)能跑。 - 执行器不提供内核隔离时,再由逐次 shell 审批兜底——提示会说明该命令拥有你的完整用户权限。
这是刻意的**故障关闭(fail-closed)**设计:无法强制执行所请求的模式时,调用以 SANDBOX_UNAVAILABLE 失败,绝不静默无限制放行。错误文本会指明缺失的平台 runner。
如果内核禁用了非特权 user namespace,也可能出现同样结果:
# 检查cat /proc/sys/kernel/unprivileged_userns_clone # Debian/Ubuntu 系cat /proc/sys/user/max_user_namespacesmacOS:Seatbelt
macOS 使用系统自带的 Seatbelt(sandbox-exec)。workspace-write 的可写范围由 Seatbelt profile 与进程内 fs 栅栏共用同一份可写根目录推导,二者授予完全相同的根。
无需额外安装。若 sandbox-exec 不可用,处理方式与 Linux 相同:请求的模式无法强制执行时以 SANDBOX_UNAVAILABLE 失败。
Windows:ACL restricted-token runner
Windows 用 harness 的 ACL restricted-token runner 提供 OS 级隔离,与另两个平台一样开箱即用。单文件构建需要自带两样东西才能把它跑起来:它依赖的原生 koffi(由 apps/tui-bin/stub/koffi.js 顶替),以及 runner 进程本身——harness 用模块 specifier 定位它,而编译后的二进制答不了这个调用,于是 qialike 把 harness 自己的 runner 一并携带并充当其 launcher(见 apps/tui-bin/src/windows-acl-shim.ts)。
permission(presets)行在所有平台都已启用,Windows 不例外。
实际后果:
- 纯 JS 的
fs-sandbox栅栏 +workspace-write + ask审批边界仍是文件效应的闸门。 - ACL runner 提供内核级的进程隔离。
- 仍然可以在 WSL2 里使用 qialike(获得 Linux 的 bubblewrap / Landlock 档),但这是可选项,不是必需。见 Windows 与 WSL。
设计边界
- 强制执行完整度是逐调用报告的:
full表示后端管辖模式承诺的每个文件操作,partial表示只管辖子集。需要绝对边界的消费方可以拒绝或向上暴露partial。 - 策略随调用传递,不固定在 provider 上:两个消费方可以同时按不同策略隔离;获批的升权重试只是一次用更宽策略发起的新调用。
- 机密文件读不到:
.env系列、.git内部路径与 harness 凭据文档一律拒绝读取(.env.example例外)。这条在任何沙箱模式下都生效,danger-full-access也不解除。它只拦读工具:shell 命令里点名这些文件仍读得到——这是如实记录的缺口,Gemini CLI 同样存在。 - 仓库无权放宽你的沙箱:改(或关掉)
sandbox/sandbox-policy/fs-sandbox/bash-sandbox/pwsh-sandbox/approval/permission/fs-observation-policy的行只能写在你自己的 overlay 里;仓库级 overlay 里的这类行一律被拒绝。详见 配置。
下一步
- Windows 与 WSL —— Windows 原生使用,或可选地改走 WSL2
- 故障排除 ——
SANDBOX_UNAVAILABLE的处理 - 命令 ——
qialike --dump-config查看组合后的分层