沙箱化代码执行

adk-sandbox crate 为 ADK agent 提供隔离的代码执行,具有两个级别的隔离:

  1. 进程隔离 — 具有环境隔离和超时强制执行的子进程
  2. 操作系统级沙箱配置文件 — 对文件系统、网络和进程创建的内核级限制

后端

后端隔离级别语言功能标志
ProcessBackend环境 + 超时Rust, Python, JS, TS, 命令process(默认)
ProcessBackend + sandbox内核级同上process + sandbox-native
WasmBackend完整(内存、文件系统、网络)仅 WASMwasm

你得到的是哪种隔离?

ProcessBackend::isolation() 报告了它,因此这不是可以从 crate 名称推断出来的:

结果含义
IsolationClass::SubprocessOnly一个带有已清空环境、超时限制以及自身进程组的子进程。操作系统不再施加进一步限制:代码可以读取宿主文件系统并访问网络。这就是 ProcessBackend::default() 提供给你的能力。
IsolationClass::OsEnforced已附加一个强制执行器 一个策略,因此操作系统会限制该子进程。

关于进程后端,有两点值得了解:

  • 程序会在清空环境之前解析。 一个裸的 python3noderustc 会在调用者的 PATH 上查找,并作为绝对路径传递给子进程。这意味着子进程启动时不需要自己的 PATH——此前调用者必须把 PATH 放在 ExecRequest::env 中,这也让已执行的代码能够在其上启动其他任何东西。
  • 编译通过与执行相同的边界运行。 过去,Rust 源代码是通过在共享路径之外构建的命令来编译的,因此编译过程没有 enforcer 包装器、没有超时、也没有进程组。这很重要,因为编译并不是静态不变的:include_str! 会读取文件,而过程宏会在生成的二进制存在之前运行任意代码。编译阶段会接收一个平台特定的 toolchain allow-list;在 Windows 上,这包括 LIB,并使用 Rust toolchain 的 rust-lld linker,因此不会选择 link.exe 之前在 PATH 上的无关项。OS enforcer 正是约束该阶段的机制。

环境优先级

SandboxPolicy::env 为每次执行提供默认值,而 ExecRequest::env 会按调用逐一覆盖它们。此前 policy 的变量完全被忽略了。

OS 沙箱配置文件

OS 级沙箱执行会在内核级别限制子进程。这超出了环境隔离的范围——操作系统本身会阻止未经授权的文件系统访问、网络连接和进程创建。

平台支持

平台执行器工作方式
macOSSeatbelt (sandbox-exec)系统调用级规则:“默认允许,危险拒绝”——拒绝写入、网络和 fork;读取不受限制
Linuxbubblewrap (bwrap)文件系统命名空间隔离(白名单挂载)
WindowsAppContainer未实现 — 强制器报告自身不可用

快速开始

use adk_sandbox::{
    ProcessBackend, ProcessConfig, SandboxBackend,
    SandboxPolicyBuilder, get_enforcer,
};

// 1. Define what the sandboxed process can do
let policy = SandboxPolicyBuilder::new()
    .allow_read("/usr")           // Read system libraries
    .allow_read_write("/tmp/work") // Write to work directory
    .allow_process_spawn()         // Python needs to exec
    // Network is denied by default
    .env("PATH", "/usr/bin:/usr/local/bin")
    .build();

// 2. Get the platform-appropriate enforcer
let enforcer = get_enforcer()?;

// 3. Create a sandboxed backend
let backend = ProcessBackend::with_sandbox(
    ProcessConfig::default(),
    enforcer,
    policy,
);

// 4. Execute code — network is blocked, writes restricted
let result = backend.execute(request).await?;

功能标志

[dependencies]
# Auto-detect platform enforcer
adk-sandbox = { version = "2.0.0", features = ["process", "sandbox-native"] }

# Or pick a specific platform
adk-sandbox = { version = "2.0.0", features = ["process", "sandbox-macos"] }
adk-sandbox = { version = "2.0.0", features = ["process", "sandbox-linux"] }

SandboxPolicy

策略定义了沙箱化进程被允许执行的操作:

字段默认值描述
allowed_paths[] (拒绝所有)具有只读或读写访问权限的文件系统路径
allow_networkfalse是否允许网络访问
allow_process_spawnfalse是否允许生成子进程
env{}沙箱化进程的环境变量

平台差异

macOS(Seatbelt): 使用“默认允许,危险项拒绝”——默认拥有完全访问权限,然后阻止网络、文件写入和进程创建。纯白名单方式行不通,因为 Python 在启动时需要几十个 macOS 特定的 syscall 类别。

Linux(bubblewrap): 使用基于命名空间的白名单——默认什么都不存在,只挂载所需内容。使用 apt install bubblewrapdnf install bubblewrap 安装。

Windows(AppContainer): 未实现。设计上是基于令牌的 ACL——带有默认无访问权限的受限 SID,然后在特定路径上授予 ACL——但容器创建、ACL、capabilities 和 job-object 清理都缺失,因此 probe() 返回 EnforcerUnavailable。在 Windows 上不带 enforcer 运行,或者使用 macOS 或 Linux,因为只有这些平台上的强制执行是真实生效的。

示例

参见 examples/sandbox_agent/,了解一个完整的由 LLM-agent 驱动的示例,它在受沙箱保护的环境中执行 Python 代码,并由操作系统内核阻止网络访问。