OpenSquilla Sandbox
Sandbox system · technical deep dive

不是“套一层容器”,
而是统一执行边界

OpenSquilla 的难点是让 shell、文件、代码执行、网络、后台进程、子代理和 Coding Task 在 Windows、Linux、macOS 上遵守同一套权限语义,同时又能完成真实的本地任务。

30 秒回答:我把原来分散的 sandbox 开关、approval bypass、敏感路径和 workspace 规则收敛成三态运行模式;用 RunContext 统一携带路径与网络授权,用确定性 OperationProfile 和 action fingerprint 做精确决策,再由 Bubblewrap、Seatbelt、Windows restricted token/ACL/firewall 等原生能力执行。后端不可用时失败闭合,Full Host 也不会抹掉独立的工具 deny 与注入防护。
01 · The real problem

一开始要解决的,不是隔离本身

旧系统已经有沙箱,但用户看到的开关和真实边界不一致:Web UI 的“绕过审批”看似放开权限,实际仍被 workspace、敏感路径和 mount 拒绝;同一动作在 shell、filesystem、后台任务和子代理中又可能走不同逻辑。

SEMANTICS

语义分裂

sandboxsecurity_grading、approval mode 多个布尔值组合,无法回答“到底在宿主还是隔离内执行”。

CONSISTENCY

工具不一致

文件工具会检查路径,shell 的 workdir、重定向、后台进程或网络子进程却可能绕过同一边界。

USABILITY

安全与可用性冲突

全拒绝会让安装、搜索、读取外部项目无法完成;全放开又会让一次批准扩散成会话级权限。

02 · Technology choice

为什么不用 Docker,而用系统原生限制?

结论:不是认为 Docker 不安全,而是它与“本地桌面代理、按命令临时隔离、需要受控访问宿主资源”的主要场景不匹配。Docker 更适合稳定服务、CI 和多租户任务;OpenSquilla 需要的是策略控制面加平台原生执行后端。

维度Docker系统原生后端本项目判断
部署成本依赖 daemon、镜像、网络与 volume;macOS/Windows 通常还经过 VM。复用 OS 已有原语,按命令创建短生命周期边界。桌面首次使用和跨平台分发更轻。
宿主任务容器内的 package manager、注册表、服务、GUI、进程视图不是宿主本身;想操作宿主通常要额外挂载或高权限桥接。可在 policy 批准后针对精确 host effect 执行。安装/卸载/探测是真实需求,不能假装在容器里完成。
文件语义需要预先设计 volume;动态外部路径、单次 ro/rw grant 会转化为容器重建与挂载管理。RunContext 直接把 workspace、ro/rw mount 映射给后端。更适合会话中动态批准一个路径。
策略问题能隔离进程,但不会自动解决“谁批准、批准哪个路径/域名、是否传播给子代理”。这些由统一策略层解决,后端只兑现 policy。真正复杂的是控制面,不是启动容器。
隔离强度Linux 上本质也基于 namespace/cgroup/seccomp,工具链成熟;配置合理时隔离稳定。各平台强度不同,需要能力探测、显式降级和失败闭合。原生方案更贴合,但必须承认平台差异。
NATIVE BACKENDS

具体怎么落地

  • Linux:Bubblewrap + namespace + bind mount + seccomp/limits
  • macOS:Seatbelt profile
  • Windows:restricted token/identity + ACL + firewall/WFP
  • 共享:受管代理、进程内网络守卫、路径与授权策略
WHEN DOCKER WINS

什么时候反而应该选 Docker

服务端多租户、可预构建固定镜像、任务不需要影响宿主、要求可复现依赖环境时,Docker 是更自然的后端。合理演进方向是把它作为另一种 Backend,而不是替代上层 RunMode/RunContext。

03 · Security model

为什么是三种模式,而不是开/关?

Standard-Sandbox

始终以 sandbox 为执行目标;跨 workspace、额外网络或敏感动作必须形成明确批准。后端不可用时直接失败。

Managed Execution

仍默认在 sandbox 内执行;普通公网、非敏感临时路径和可识别 host effect 可由确定性规则处理,越界只对精确动作授权。

Full Host Access

执行目标改为 host,仅对允许主体开放;绕过沙箱批准门,但显式工具 deny、注入来源拒绝和外传防护仍独立存在。

关键区分:Managed 是“在隔离模型内减少不必要阻塞”,Full 是“改变执行目标”。auto-approve 只能处理当前模式中的批准,不能把 Standard 升级成 Managed 或 Full。
04 · Architecture

从一次调用到真正执行

RunMode先锁定执行目标
Principal校验主体可选模式
RunContextworkspace + grants
OperationProfile路径/网络/host effect
Policy & Approval规则 + 精确指纹
Backend隔离执行或精确 host retry
上下文层

会话中统一保存 workspace、ro/rw mount、domain、public network、package bundle 和 temporary grant,并定义子代理继承规则。

run_context.py
run_context_service.py
描述层

把 shell、文件、网络、后台进程等变成统一操作描述;分类器合并 requested paths、write paths、domains、destructive intent 与 host effect。

operation_runtime.py
operation_profile.py
授权层

对越界动作生成 action fingerprint;批准返回 continuation,重试时重新计算并单次消费,防止“批准 A、执行 B”。

elevation.py
escalation.py
网络层

子进程走受管代理,Gateway 内 HTTP 调用走进程内守卫;连接时验证最终 IP,拒绝私网、数字 IP 与 DNS 重绑定。

network_guard.py
network_proxy.py
平台层

Backend 只兑现 policy;必须声明 available/capability,初始化失败抛出明确错误,不能静默回落到宿主。

linux_bwrap.py
seatbelt.py
windows_default.py
05 · Hard parts

最有技术含量的坑

这些问题都不是“少写一个 if”,而是边界对象、访问级别或执行位置发生漂移。

01

workspace 被敏感根误伤

问题:/root/.opensquilla/workspace 先命中 `/root` 敏感规则。

解法:规范化后先识别精确 workspace,再应用宽泛敏感根;测试固定规则顺序。

02

写请求拿到只读 grant

问题:审批显示成功,重试仍报 mount_requires_write_access

解法:approval choice 从真实 access 生成;rw 请求不能用 ro 选择完成。

03

网络分类吞掉输出路径

问题:curl -o /mnt/out URL 只获得域名授权,没有写挂载。

解法:分类器合并网络、读写路径和 host effect,禁止 early return 覆盖已有证据。

04

外部 cwd 变成可写 workspace

问题:只批准 ro workdir,后端却按 workspace 以 rw 挂载。

解法:区分会话 workspace 与执行 cwd;后者按 grant 独立挂载。

05

混合 shell 整段被提升

问题:where winget; Set-Content ... 因第一段 host probe 让后续写入也走 host。

解法:host routing 不能跳过路径门;必要时拆分命令,授权绑定精确目标。

06

Windows 子进程收不到 EOF

问题:Proactor 下关闭 stdin 未等待 wait_closed(),CI 重复超时。

解法:前后台 host exec 都等待关闭完成,并做连续多轮回归。

07

Full Host 在子链路丢失

问题:子代理/Coding Task 重建 context 时使用默认值,悄悄重新启用 sandbox。

解法:run mode、workspace、mount、principal 显式序列化;临时 grant 按继承规则处理。

08

Windows 首次初始化冻结事件循环

问题:async task 内同步 WaitForSingleObject(INFINITE),Desktop 45 秒先超时。

方向:移入线程/工作进程,并把 setup 状态暴露给 Desktop。

06 · Technical questions

可能继续追问什么

回答模板固定为:先给结论,再解释约束与机制,最后主动承认取舍。这样既避免背诵感,也不会把安全问题答成产品口号。

20 个问题 · 点击展开
1. 为什么不用 Docker?
结论Docker 不是不安全,而是不匹配本地桌面代理的主要执行模型。原因它引入 daemon/镜像/volume/VM 成本;容器内无法自然完成宿主安装、注册表、服务和进程管理;动态单次路径授权也会变成挂载生命周期问题。取舍原生后端部署轻、能精确处理 host effect,但平台隔离强度不完全一致,所以必须能力探测和失败闭合。

继续追问:Docker 何时更合适?答:服务端多租户、固定镜像、CI、完全不需要影响宿主时;可以作为未来 Backend,但替代不了 RunContext 与审批控制面。

2. Docker 本身不也是系统原生隔离吗?

是。Linux Docker 底层同样依赖 namespace、cgroup、capability、seccomp。这里的区别不是“原生 vs 非原生的安全原语”,而是是否引入容器运行时、镜像文件系统与 volume 模型。OpenSquilla 直接调用底层能力,更适合 per-command ephemeral sandbox 和动态宿主授权。

不要回答:“Docker 太重所以不安全”。重是运维取舍,不是安全结论。

3. 系统原生方案会不会比 Docker 更不安全?

不能一概而论。Linux Bubblewrap 可提供强 namespace/mount/seccomp 边界;macOS Seatbelt 与 Windows 组合机制能力不同。设计上不宣称三平台等强,而是通过 Backend capability、明确 unavailable 和失败闭合避免“假隔离”。高风险多租户仍应优先更强的 VM/container 边界。

4. 为什么三种模式,两种模式不够?

开/关只能表达执行位置,无法表达“仍隔离,但对普通操作减少重复确认”。Managed 解决可用性,Full 改变执行目标;二者不能合并,否则自动规则很容易演化成隐式 host access。

5. Managed Execution 到底自动允许什么?

不是一张无限白名单,而是按 OperationProfile 判断:正常公网、已知包网络束、非敏感临时路径、明确的安装/探测 host effect 等。敏感路径、关键删除、系统破坏、高置信外传和未知动作仍拒绝或要求精确批准。

6. 为什么不用模型判断一个动作是否安全?

安全裁决需要可重复、低延迟、离线可用、能做回归。模型输出受版本、上下文和采样影响,同一动作可能得到不同结论。确定性规则的代价是维护成本,但输入、输出和覆盖范围可证明;未知行为按保守默认处理。

7. action fingerprint 包含什么?

至少覆盖 tool、action kind、规范化 argv、cwd、目标读写路径、会话/主体和关键 policy 参数。批准返回 continuation;执行前重新计算并匹配,只消费一次,防止参数或路径变化后复用旧批准。

8. 怎样处理 TOCTOU 和符号链接?

策略阶段做 symlink-aware canonicalization 只是第一层;强保证要靠后端 mount view、no-follow/openat 类访问、父目录验证和创建/重命名前复查。仅用 Path.resolve() 无法消除检查到系统调用之间的竞态。

9. 不存在的目标路径怎么规范化?

不能直接 resolve 叶子。做法是找到最近存在祖先,规范化祖先后按平台词法规则拼回剩余片段,再校验 denied root/glob;Windows 还要处理盘符、UNC、大小写折叠、junction 与设备路径。

10. 为什么网络既要代理,又要进程内守卫?

shell/代码子进程可通过 proxy env 和平台网络边界约束;Gateway 内的 httpx、provider、search 调用不一定创建子进程,也可能不读取环境变量。两层共享同一个 NetworkDecision,覆盖不同执行形态。

11. 域名 allowlist 为什么还不够?

允许域名可能解析到 loopback、RFC1918、链路本地或云元数据地址,攻击者还可做 DNS 重绑定。代理必须在真正连接时验证最终 IP,并处理 Host、absolute URL、CONNECT authority 不一致,拒绝直接数字 IP 绕过。

12. Backend 不可用时为什么不能自动跑宿主?

基础设施失败不等于用户授予宿主权限。Standard 直接失败;Managed 只能返回结构化 denial,在用户或规则对同一个 fingerprint 形成批准后做精确 host retry。否则就是静默安全降级。

13. auto-approve 为什么不能触发 host routing?

approval behavior 回答“如何处理批准”,RunMode 回答“在哪执行”。二者顺序必须固定:先锁定执行边界,再解析批准。否则 Standard + auto-approve 会被错误升级成 Managed/Full。

14. 混合 shell 命令怎么防止权限扩大?

不能因为脚本中出现一个 host probe 就把整段放到宿主。分类器要保留每个读写目标,host routing 仍必须经过 path/write policy;高风险场景拆分子命令,fingerprint 绑定精确 argv 与目标。

15. Full Host Access 是否等于所有安全检查关闭?

不是。它关闭 sandbox enforcement 与相关 approval gates,但显式 denied tools、提示注入来源拒绝、敏感数据外传保护和 mutation telemetry 是独立边界。分层设计避免“一个开关删除所有控制”。

16. 子代理为什么不能直接继承所有 grant?

run mode、workspace 和明确长期 grant 可以按契约继承;一次性 grant 具有 action/session 所有权,盲目复制会把一次批准扩散到多个执行者。派生 RunContext 必须显式定义哪些能力继承、哪些重新批准。

17. Windows 和 Linux 如何保证接口一致?

一致的是 policy 输入、result/error 契约和 capability 描述,不是假装底层实现相同。Linux 映射到 namespace/mount/seccomp;Windows 映射到 restricted identity、ACL、firewall/WFP。无法兑现的 operation domain 必须报告 unsupported。

18. 如何设计测试矩阵?

mode × principal × tool domain × platform × boundary × approval outcome × execution shape 组合,而不是追求测试数量。优先覆盖交叉不变量:Standard+auto-approve+host effect、Managed+external rw+background network、Full+subagent+explicit deny。

19. 这个方案最大的缺点是什么?

跨平台实现和规则维护成本高,隔离强度也不完全一致;OperationProfile 对 shell wrapper、未来路径和新 package manager 需要持续扩展。缓解手段是能力显式化、保守默认、属性/模糊测试,以及未来增加 Docker/VM Backend 处理更强隔离场景。

20. 如果继续优化,优先做什么?

第一,修复 Windows 首次 setup 阻塞事件循环并暴露 configuring 状态;第二,用 property/fuzz 测试覆盖路径、shell token 与代理协议解析;第三,建立 Backend conformance suite,明确三平台能力差距;第四,为高风险/多租户场景增加容器或 VM 后端。

07 · Evidence

公开证据链

只保留与沙箱直接相关的起点、主线合入、定向修正和当前遗留问题。