Agent Governance Toolkit MXC Sandbox Provider:基于 MXC 原生二进制的轻量级 Agent 代码沙箱实战指南
【免费下载链接】agent-governance-toolkitAI Agent Governance Toolkit — Policy enforcement, zero-trust identity, execution sandboxing, and reliability engineering for autonomous AI agents. Covers 10/10 OWASP Agentic Top 10.项目地址: https://gitcode.com/GitHub_Trending/ag/agent-governance-toolkit
导读
本文围绕 Agent Governance Toolkit 中agent-sandbox的MXC Sandbox Provider设计展开,讲解如何用 Microsoft eXecution Container(MXC)原生二进制为自主 Agent 提供"进程级、一次性、无常驻进程"的代码隔离沙箱。读完本文,你将掌握 MXC Provider 的会话(Session)模型与配置映射机制、失败闭合(fail-closed)的网络与挂载约束、原生治理(Native Governance)与静态代码扫描的执行时序,以及run_once与完整生命周期两种执行方式的选择依据,可直接在 Agent 代码执行场景中落地使用。
一、设计总览:用原生二进制驱动、无常驻沙箱进程
设计文档 docs/proposals/MXC-SANDBOX-PROVIDER.md 开宗明义地定义了本模块的架构基调:
MxcSandboxProviderdrives the native MXC executable and keeps no long-lived sandbox process. A session owns a workspace whose scripts are mounted read-only and whose output directory is mounted read-write.
一句话概括:Provider 直接驱动 MXC 原生可执行文件,不保留任何长期存活的沙箱进程;一次会话(session)持有一个工作区(workspace),其中脚本目录只读挂载、输出目录读写挂载。
MXC(Microsoft eXecution Container)是一个"原生、以 JSON 配置驱动"的沙箱运行器,支持 Windows(ProcessContainer)、Linux(Bubblewrap / LXC)、macOS(Seatbelt)以及实验性的 MicroVM / Hyperlight / Windows Sandbox 等包含后端。MXC不提供 Python SDK,因此本 Provider 的集成方式是以子进程方式拉起wxc-exec(Windows)/lxc-exec(Linux)/mxc-exec-mac(macOS)二进制,并将一个由MxcConfig渲染出的 JSON 配置文档喂给它——见 provider.py 与 config.py 的模块文档。
从源码结构看,该 Provider 实现了SandboxProvider抽象基类(sandbox_provider.py),与 Docker、Hyperlight、ACA 等 Provider 平级,统一暴露create_session/execute_code/destroy_session三个核心生命周期方法。
二、会话模型:会话是"配置包",不是运行中的进程
2.1 MXC 二进制是一次性的
MXC 稳定版原生二进制是one-shot语义:provision(供应)→ start(启动)→ exec(执行)→ stop(停止)→ deprovision(销毁),进程退出即沙箱销毁。它不像 Docker 容器或 Hyperlight 微虚拟机那样存在一个可跨调用复用的常驻 guest。
2.2 会话 = 持久化的"bundle"
为了满足基于会话的SandboxProvider契约,本 Provider 把"会话"建模为一份持久化 bundle,而非运行中的进程,其组成为(见_Session类与create_session实现):
- 解析后的
MxcConfig(已映射完成的沙箱配置); - 可选的策略求值器(evaluator,来自原生治理 runtime);
- 每个会话独立的工作区目录:
scripts/(只读挂载给沙箱)与output/(读写挂载给沙箱); - 解释器命令(默认
python)。
每次execute_code(或run)都会基于该 bundle 拉起一个全新的 one-shot MXC 沙箱。由此带来的关键语义是:
同一会话内多次执行之间,guest 状态不持久——内存变量、解释器状态,以及写在会话读写工作区之外的数据,都会在每次调用退出时被丢弃。需要跨调用持久化的调用方,应写入会话的读写
output/目录,它会在主机侧跨执行保留。
(MXC 的 TypeScript SDK 与0.7.0-devschema 提供了有状态的 provision/exec/stop 生命周期,但该路径被留作未来增强,不在当前二进制驱动 Provider 的范围内。)
2.3 工作区的构造细节
在create_session中,Provider 会:
- 用
tempfile.mkdtemp(prefix=f"mxc-{agent_id}-{session_id}-")创建主机侧工作区; - 创建
scripts/与output/两个子目录; - 把
scripts/追加进MxcConfig.readonly_paths,把output/追加进readwrite_paths; - 将
(agent_id, session_id)注册进内部的会话字典(使用RLock保护,因为异步变体委托给同步实现,销毁可能与注册表读取重叠)。
三、配置映射:MxcConfig.from_sandbox_config与失败闭合约束
3.1 通用配置 → MXC JSON 的映射规则
MxcConfig.from_sandbox_config(config.py)将通用的SandboxConfig翻译为 Provider 专属的MxcConfig,映射关系如下:
SandboxConfig字段 | MxcConfig字段 | 渲染到 MXC JSON 的位置 |
|---|---|---|
timeout_seconds | timeout_ms(×1000,最小 1ms) | timeoutMs |
input_dir | readonly_paths(追加) | filesystem.readonlyPaths |
output_dir | readwrite_paths(追加) | filesystem.readwritePaths |
network_enabled+network_allowlist | allow_outbound+allowed_hosts | network.allowOutbound+network.allowedHosts |
network_default="allow"(且无 allowlist) | allow_unrestricted_egress=True | network.allowOutbound=true(无 host 过滤) |
env_vars | env_vars(渲染前经sanitize_env_vars清洗) | process.environment |
MxcConfig的默认值:schema 版本0.6.0-alpha(当前各平台推荐的稳定 schema)、timeout_ms=60000、allow_outbound=False、allow_unrestricted_egress=False、backend=None。
3.2 网络出口:默认失败闭合
设计文档强调:"Filtered egress usesnetwork.allowedHosts. Unrestricted egress requires explicit default allow."源码中_check_egress强制执行这一契约:
- 当
allow_outbound=True但allowed_hosts为空且未显式设置allow_unrestricted_egress时,直接抛出ValueError; - 唯一的"不受限出口"路径是显式开启:例如策略层下发
defaults.network_default: allow; - 这样配置永远不会静默地变成"任意主机可访问"。
3.3 受保护挂载路径:拒绝系统目录
from_sandbox_config会对input_dir/output_dir调用validate_mount_path(实现在 _hardening.py)。该守卫会拒绝挂载以下系统目录:
- Unix 系:
/、/etc、/proc、/sys、/usr、/var、/boot、/dev、/sbin、/bin、/lib; - Windows 系:
C:\Windows、C:\Program Files、C:\ProgramData等(大小写不敏感,且按 realpath 比较); - Windows 根级目录
C:\Users整目录(但允许挂载其下的具体子目录,如C:\Users\agent\workspace)。
此外sanitize_env_vars会剥除LD_PRELOAD、LD_LIBRARY_PATH、BASH_ENV、PYTHONSTARTUP、PYTHONPATH、NODE_OPTIONS、JAVA_TOOL_OPTIONS等会在解释器/加载器启动时生效、从而绕过沙箱加固的危险环境变量。
3.4 工具白名单与 CPU/内存:MXC 不承诺就不渲染
设计文档明确指出两点边界:
- MXC 没有工具注册通道。因此
SandboxConfig.tool_allowlist非空时,create_session会直接抛出ValueError——不是静默忽略,而是失败闭合。需要工具门控时请改用 Docker 或 Hyperlight 后端。 - CPU 与内存限制不在
0.6.0-alpha稳定 schema 中表达,from_sandbox_config会丢弃memory_mb/cpu_limit,由所选包含后端自身的资源模型负责。
同样的原则延伸到 JSON 渲染:to_mxc_json只输出 MXC 真实支持的键,绝不输出无法兑现的声明。对于操作者需要的额外 schema 键(如 UI policy、后端专属调优),可通过extra_config原样合并,且_reassert_security_keys会在合并之后重新钉死network.allowOutbound、allowedHosts、filesystem.*、timeoutMs,防止一段 verbatim 片段削弱安全键。
一个典型的渲染结果(来自 mxc-quickstart 教程):
{ "version": "0.6.0-alpha", "process": { "commandLine": "python /scripts/run.py" }, "filesystem": { "readonlyPaths": ["/data/user-pdf"], "readwritePaths": ["/data/agent-out"] }, "network": { "allowOutbound": true, "allowedHosts": ["pypi.org", "*.github.com"] }, "timeoutMs": 30000 }四、原生治理:执行前的宿主侧把关
设计文档的 "Native governance" 一节点出了本 Provider 的安全时序核心:
create_session(..., runtime=runtime, config=config)stores aHostSession. Everyexecute_codecall evaluates before the static scan and before MXC is spawned.
具体链路如下:
create_session时:若传入runtime,Provider 通过_build_runtime_session从agent_control_specification导入并构造HostSession(runtime, agent_id=..., session_id=...),随会话 bundle 一并保存;- 每次
execute_code时(在沙箱拉起之前):- 先调用
session.evaluator.pre_tool_call(tool_name="sandbox_execute", args=eval_ctx, ...)做策略判定,eval_ctx携带agent_id、action="execute"、code以及可选的context; - 若返回transform 判定(
applies_transform),由于沙箱无法改写即将执行的代码,直接拒绝(抛PermissionError); - 若判定为deny,抛出
PermissionError,被拒策略永远不会到达 MXC; - 通过后才进入下一步。
- 先调用
该时序保证:策略拒绝发生在任何沙箱进程产生之前,实现了"主机侧零成本拒绝"。
五、一次性执行与完整生命周期
5.1run_once:开箱即用的隔离执行
设计文档指出:run_oncecreates a session, executes once, and destroys the workspace.
from agent_sandbox import MxcSandboxProvider, SandboxConfig provider = MxcSandboxProvider(backend="bubblewrap") execution = provider.run_once( "tutorial-agent", "print('hello from the MXC sandbox')", config=SandboxConfig(timeout_seconds=20, network_enabled=False), ) result = execution.result print("exit:", result.exit_code, "ok:", result.success) print(result.stdout)run_once是create_session → execute_code → destroy_session的便捷封装(含try/finally确保会话销毁),每次调用完全隔离:内存变量与读写工作区之外的写入全部丢弃。异步场景可用run_once_async(通过asyncio.to_thread委托)。
5.2 完整生命周期:跨调用共享输出
当多次调用必须共享输出文件时,应使用完整生命周期:
handle = provider.create_session("pdf-agent", runtime=runtime, config=config) try: for chunk in chunks: execution = provider.execute_code( handle.agent_id, handle.session_id, chunk_code ) # 读取 session 的 output/ 目录,跨调用持久 finally: provider.destroy_session(handle.agent_id, handle.session_id)destroy_session无需停止任何存活进程(one-shot 沙箱每次执行后已自行销毁),只需shutil.rmtree清理主机侧工作区。
5.3 低层run与execute_code的差异
run(agent_id, command, config, session_id=...):直接以list[str]命令在沙箱内执行,可复用已有会话(找不到会话时构建一次性临时 bundle);适合非 Python 语言或任意命令行。execute_code(agent_id, session_id, code, context=...):面向 Python 代码——把代码写入scripts/{execution_id}.py,以<interpreter> <script>形式执行(避免 shell 引号问题);context通过MXC_CONTEXT环境变量以 JSON 暴露给 guest,不改写提交的代码。
需要注意:execute_code只支持 Python 解释器。静态扫描器(enforce_no_subprocess_execution,见 code_scanner.py)基于 Python AST,只能审查 Python;配置了其他解释器时会拒绝执行(否则会运行未经扫描的代码,造成虚假安全感),并引导调用方改用run()。
六、纵深防御:四次执行前的检查层
结合教程与源码,每次执行实际经过四层防护(按顺序):
- 原生 ACS 治理门:
AgentControl可在任何沙箱拉起前拒绝(见上文第四节); - 静态代码扫描:
enforce_no_subprocess_execution拒绝subprocess.run/call/Popen、os.system、os.exec*、pty.spawn、shutil.which等明显的进程派生 API(含importlib.import_module/__import__动态导入的别名解析); - MXC 包含:文件系统/网络策略由操作系统后端执行(bubblewrap 绑定、网络策略、
timeoutMs); - 进程环境隔离:MXCrunner 进程只接收按平台白名单转发的最小环境(Windows 转发
PATH/SYSTEMROOT/LOCALAPPDATA等;Linux/Darwin 转发PATH/HOME/TMPDIR等),绝不继承父进程完整环境,宿主密钥不会泄漏给 launcher;而 guest 的环境则由配置中的process.environment单独管控。
七、二进制发现与实战注意事项
7.1 二进制解析顺序
Provider 构造时按以下顺序解析 MXC 二进制(_resolve_binary):
- 显式
binary_path=参数; MXC_BINARY环境变量;PATH中按平台查找:Linux →lxc-exec,Windows →wxc-exec.exe/wxc-exec,macOS →mxc-exec-mac。
找不到二进制不会抛异常,而是通过is_available()返回False并记录原因,调用方可优雅降级。构造时若传入backend,会先构造一个临时MxcConfig做急切实参校验,让错误配置在构造期暴露而非首次使用时。
7.2 后端与实验模式
- 稳定后端:
processcontainer(Windows)、bubblewrap、lxc(Linux); - 实验后端:
windows_sandbox、wslc、microvm、seatbelt、isolation_session、hyperlight——选择实验后端会自动强制--experimental标志(needs_experimental); backend=None时由 MXC 选平台默认(Windows 为 processcontainer、Linux 为 bubblewrap、macOS 为 seatbelt)。
7.3 其他运行细节
- 超时:
subprocess.run的硬超时 =timeout_ms/1000 + 5 秒(_TEARDOWN_GRACE_SECONDS),给 MXC 自身 provision/teardown 留出宽限,只在 MXC 卡死时才强杀; - 输出截断:每路 stdout/stderr 上限 1 MiB(
_OUTPUT_MAX_BYTES),超限追加[...output truncated at byte limit]标记; - agent_id 校验:必须匹配
[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127},防止恶意 agent_id 做路径穿越或注入控制字符(会用于日志、工作区目录名、配置文件名)。
八、可验证依据与快速上手
- 设计文档:docs/proposals/MXC-SANDBOX-PROVIDER.md
- 核心实现:provider.py、config.py
- 公共抽象与配置:sandbox_provider.py
- 加固原语:
_hardening.py - 静态扫描器:
code_scanner.py - 可运行教程:mxc-quickstart/README.md 与配套脚本 quickstart.py
- 单元测试:tests/test_mxc_sandbox.py(以
sys.executable充当二进制、monkeypatchsubprocess.run,保证测试密闭、无需真实 MXC)
快速运行教程脚本:
export MXC_BINARY=/path/to/lxc-exec # 或放入 PATH python agent-governance-python/agent-sandbox/tutorials/mxc-quickstart/quickstart.py脚本会打印 MXC 可用性、渲染出的配置 JSON,并在存在二进制时实际执行一小段沙箱代码。需要提醒的是:MXC 目前属于早期预览,应作为纵深防御的一环而非硬性安全边界,直到其稳定下来;在 Agent 治理体系中,它是承载不可信(Ring 3)Agent 代码的首选包含后端之一,与上层的策略引擎、静态扫描共同构成"宿主治理 + 沙箱隔离"的完整防线。
【免费下载链接】agent-governance-toolkitAI Agent Governance Toolkit — Policy enforcement, zero-trust identity, execution sandboxing, and reliability engineering for autonomous AI agents. Covers 10/10 OWASP Agentic Top 10.项目地址: https://gitcode.com/GitHub_Trending/ag/agent-governance-toolkit
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考