Agent Runtime 与 Sandbox:当 AI 开始执行代码,谁来保证系统安全?
从 Codex、Claude Code 到生产级 Agent 执行环境:深入理解沙箱隔离、文件与网络权限、密钥保护、长任务恢复和安全执行架构
一、当 Agent 获得 Shell 权限,真正的问题才刚刚开始
假设我们正在开发一个 AI 编程 Agent。
用户给它一个很普通的任务:
“帮我检查项目依赖,修复运行失败的问题,并执行测试。”
Agent 开始分析项目,发现依赖缺失,于是执行:
pip install -r requirements.txt
随后,它读取代码、修改文件、运行测试,并向用户报告:
“问题已经修复,所有测试通过。”
看起来,这是一次非常成功的 Agent 执行。
但是,如果这个项目的依赖文件被攻击者修改了呢?
如果某个依赖安装脚本试图读取用户的 SSH 私钥呢?
如果测试程序偷偷向外部服务器发送环境变量呢?
如果 Agent 在修复过程中误删了项目外的文件呢?
这时,我们会发现:
问题已经不再是模型是否正确理解用户的任务,而是模型生成的操作能否安全执行。
在上一篇《Tool Calling 与 MCP:Agent 如何安全地操作真实世界?》中,我们讨论了工具调用的权限边界。
但工具授权只能解决一部分问题。
即使用户明确批准 Agent 运行测试,也不代表测试过程中启动的所有子进程都应该获得用户电脑的完整权限。
即使 Agent 只执行一条正常的命令,这条命令所加载的依赖、脚本和插件,也可能产生额外行为。
因此,现代 Coding Agent 必须拥有一个独立于模型推理过程的执行环境。
这就是 Agent Runtime 与 Sandbox 的核心价值。
二、Agent Runtime 和 Sandbox 分别是什么?
这两个概念经常被混在一起,但它们并不相同。
Agent Runtime:负责让任务持续执行
Agent Runtime 可以理解为 Agent 的运行时系统。
它管理模型调用、任务状态、工具执行、事件流、错误处理、任务暂停和恢复。
例如:
用户要求 Agent 修复 Bug。
Runtime 需要协调:
-
调用模型分析任务。
-
接收工具调用请求。
-
检查工具权限。
-
启动执行环境。
-
执行命令或文件操作。
-
收集执行结果。
-
反馈给模型。
-
保存任务状态。
-
继续下一轮执行。
-
完成任务并输出结果。
这些职责共同形成 Agent 的运行生命周期。
Sandbox:负责限制代码能够做什么
Sandbox,即沙箱,是一种受限执行环境。
它的目标不是提高模型推理能力,而是限制被执行程序能够访问的系统资源。
典型限制包括:
-
可读取的文件和目录。
-
可修改的目录。
-
是否能够访问网络。
-
能够连接哪些网络地址。
-
能否读取环境变量和凭据。
-
CPU、内存和进程数量。
-
是否拥有系统级权限。
-
最大运行时间。
可以这样理解:
Runtime 负责管理执行过程,Sandbox 负责限制执行权限。
一个完整的 Agent 系统通常需要两者配合。
用户任务
|
v
Agent Runtime
|
+----------+----------+
| | |
v v v
Context State Model
| | |
+----------+----------+
|
v
Tool Gateway
|
Policy & Approval
|
v
Sandbox Manager
|
+----------+----------+
| | |
v v v
Filesystem Network Resources
Isolation Policy Limits
| | |
+----------+----------+
|
v
Code Execution
|
v
Result & Artifacts
|
v
Agent Runtime
这里存在一条非常重要的信任边界:
模型可以提出执行请求,但不能自己决定是否绕过 Sandbox。
否则,Sandbox 就失去了存在的意义。
三、为什么有了权限审批,还需要 Sandbox?
传统 Agent 系统经常采用这样的安全策略:
执行操作前,弹出一个确认窗口。
例如:
“Agent 希望执行 npm install,是否允许?”
用户点击允许。
看起来,这个操作已经得到了授权。
但问题是,用户批准的是命令本身,未必了解命令执行过程中会发生什么。
一个 package manager 可能执行安装脚本。
一个测试工具可能加载第三方插件。
一个构建脚本可能读取环境变量。
这些行为不一定直接出现在最初的审批提示中。
于是我们遇到了一个典型问题:
Approval Fatigue,审批疲劳。
当 Agent 每执行几个操作就要求确认,用户可能逐渐形成习惯,几乎不再仔细阅读操作内容。
这种情况反而可能削弱安全性。
Claude Code 的沙箱实践
2025年10月20日,Anthropic 发布了《Beyond permission prompts: making Claude Code more secure and autonomous》。
文章介绍了 Claude Code 的一种重要演进:
与其让用户逐条审批所有命令,不如提前定义一个可安全操作的区域。
在这个区域内,Agent 可以相对自主地工作。
超出区域时,再触发权限审批。
Anthropic 报告称,在其内部使用中,引入沙箱后,权限确认提示减少了约84%。
这个数字来自 Anthropic 的特定内部使用环境,不代表所有 Agent 产品都能获得相同效果。
但它说明了一个很重要的工程思想:
安全边界越明确,Agent 在边界内就越有机会自主运行。
这并不是放弃审批。
而是将审批和沙箱分工:
| 机制 | 核心问题 |
|---|---|
| Approval | 是否允许这次操作越过既定边界? |
| Sandbox | 即使操作被执行,它最多能影响什么? |
| Tool Gateway | 当前用户是否有权调用这个工具? |
| Audit | 实际执行了什么? |
| Evals | 这套控制是否有效? |
只有这些机制共同工作,才能建立更可靠的执行系统。
四、Codex 与 Claude Code 如何实现 Sandbox?
当前主流 Coding Agent 并没有统一采用某一种隔离技术。
不同操作系统、运行形态和部署平台,对应的安全机制并不完全相同。
1. Codex:操作系统级沙箱与云端隔离环境
根据 OpenAI 的 Codex 沙箱文档,Codex 在本地执行命令时,会根据操作系统采用不同的隔离实现。
在 macOS 上,主要使用 Apple Seatbelt 策略。
在 Linux 上,目前的文档描述了 Bubblewrap(bwrap)与 Seccomp 等隔离机制。
Windows 和 WSL2 则有各自的执行实现。
这些机制的目的,是限制命令执行时能够访问的文件和网络资源。
例如,在受限工作区模式下,Agent 可以修改授权项目目录中的文件,却不能默认修改整个用户主目录。
如果任务需要超出当前权限范围,则需要通过额外的审批流程。
Codex Cloud 又是另一种模式。
它会在隔离的云端工作环境中执行任务,使执行进程不直接访问用户本地计算机。
云端任务拥有独立的工作区和执行状态。
但需要注意,云端隔离并不意味着云端任务天然没有任何风险。
仍然需要考虑凭据、网络权限、仓库内容以及环境配置。
2. Claude Code:文件系统与网络的双重隔离
Anthropic 在 Claude Code 沙箱设计中,特别强调两个边界。
第一是 Filesystem Isolation,文件系统隔离。
它决定 Agent 能读取或修改哪些目录。
第二是 Network Isolation,网络隔离。
它决定 Agent 能连接哪些服务器。
为什么这两个边界必须配合?
假设 Agent 可以读取整个用户目录,但不能访问网络。
那么它可能无法直接把 SSH 私钥发送到攻击者服务器。
但是,它仍可能读取或破坏敏感文件。
反过来,如果 Agent 只能写入项目目录,却能自由访问网络,也存在风险。
它可能通过网络读取恶意代码、发送项目内容,或者利用其他外部服务完成不希望发生的操作。
因此,更合理的安全设计是同时限制:
Agent 可以访问哪些文件,以及 Agent 可以连接哪些网络地址。
Anthropic 的公开实现同样采用了 macOS Seatbelt、Linux Bubblewrap 等操作系统级机制。
并通过网络代理控制对外访问。
3. 两种产品的共同思路
虽然实现细节不同,但可以提炼出几个相似原则:
-
默认限制执行权限。
-
让常规任务在授权工作区内自主完成。
-
对额外文件和网络权限进行单独控制。
-
尽可能让子进程继承隔离边界。
-
对高风险操作保留审批。
-
不把模型的自我声明当作安全保证。
这也是2026年 Coding Agent Runtime 设计中非常值得借鉴的方向。
五、Sandbox 的五层隔离机制
真正的生产级 Sandbox 不是简单启动一个 Docker 容器。
它需要根据威胁模型,建立多层约束。
第一层:Filesystem Isolation
文件系统隔离是最基础的要求。
假设用户授权 Agent 修改:
/workspace/order-service/
那么 Agent 理论上不应该能够修改:
~/.ssh/
~/.aws/
~/Documents/
更不能任意修改系统配置。
实施文件系统隔离时,需要考虑的不只是路径字符串。
还包括:
-
符号链接。
-
路径穿越。
-
挂载点。
-
容器共享目录。
-
临时目录。
-
运行时创建的文件。
-
子进程的文件访问。
例如,只检查某个路径是否以 /workspace 开头是不充分的。
攻击者可能通过符号链接让一个看似位于工作区内的路径,实际指向工作区之外。
因此,真正的隔离应该由操作系统权限、挂载命名空间或其他受信任机制实现。
第二层:Network Isolation
对于不需要联网的代码执行任务,我建议默认关闭网络。
例如:
-
执行单元测试。
-
运行简单Python代码。
-
检查数据格式。
-
生成静态报告。
这些任务通常不需要自由访问互联网。
如果任务必须联网,例如下载依赖或访问指定API,则应明确授权网络目的地。
一个成熟的网络策略应该支持:
Default: Deny
Allowed:
- 指定依赖仓库
- 指定内部服务
- 指定代理出口
Denied:
- 未授权外部地址
- 云环境元数据端点
- 内部管理网络
- 其他任务的服务
仅有域名白名单仍不一定充分。
实际系统还需要考虑DNS解析、重定向、代理、IP地址变化以及内部网络地址访问。
对于高风险场景,推荐通过受控代理或网络层策略实施出口限制,而不是让模型自己判断某个域名是否安全。
第三层:Process & System Call Isolation
Agent 可能执行任意程序。
这些程序可能调用底层操作系统接口。
因此需要限制:
-
进程权限。
-
Linux Capabilities。
-
系统调用。
-
进程创建。
-
设备访问。
-
特权操作。
在Linux容器环境中,Seccomp可以限制进程能够调用的系统调用。
Docker官方默认Seccomp配置采用允许列表思路,限制部分高风险系统调用。
但Docker也明确说明,默认Seccomp配置是兼顾安全和兼容性的基础配置,并非适合所有高风险执行场景的完整隔离方案。
对于安全性要求更高的陌生代码,可以进一步考虑gVisor或MicroVM。
第四层:Resource Isolation
Agent 生成的代码不一定恶意,也可能仅仅存在Bug。
例如:
while True:
pass
这段代码没有读取私钥,也没有访问网络。
但如果没有资源限制,它可能持续消耗CPU。
还有一些代码可能不断申请内存、创建子进程或者生成大量临时文件。
因此,Sandbox至少需要限制:
-
CPU配额。
-
内存使用量。
-
最大进程数量。
-
磁盘和临时文件空间。
-
最大执行时间。
-
输出日志大小。
资源隔离不仅是安全问题,也是成本控制问题。
如果一个Agent任务可以无限创建执行环境,那么即使没有攻击者,系统也可能因为Bug而耗尽资源。
第五层:Credential Isolation
这是生产环境中特别容易忽略的一层。
很多团队把Agent放进Docker容器之后,就认为已经安全。
但如果容器里存在:
OPENAI_API_KEY
AWS_ACCESS_KEY_ID
DATABASE_PASSWORD
GITHUB_TOKEN
那么在该容器中运行的代码,可能直接读取这些环境变量。
即使容器无法访问宿主机文件,凭据仍然可能被泄露。
因此,建议将凭据和代码执行分离。
对于不需要凭据的任务,不提供任何凭据。
对于必须访问外部服务的任务,优先通过受控服务代理执行操作。
当确实需要提供凭据时,应使用短期、最小权限、限定受众的身份凭据,并控制其使用时长和范围。
不能因为进程在Sandbox里,就允许它持有生产系统的万能密钥。
六、Docker、gVisor、MicroVM,到底应该选什么?
这是开发者在设计 Coding Agent 时经常遇到的技术选型问题。
首先需要明确:
Docker是容器运行技术,但默认Docker配置不等于针对高风险不可信代码的完整安全沙箱。
Docker容器通常与宿主机共享Linux内核。
这使它具有启动快、资源开销较低的优势,但隔离能力也受到宿主内核和运行配置的影响。
如果执行的只是团队内部已审查代码,经过加固的容器可能满足需要。
如果执行的是来自任意互联网用户的未知代码,就应该评估更强的隔离方案。
主要技术对比
| 技术 | 主要隔离机制 | 优点 | 典型场景 |
|---|---|---|---|
| macOS Seatbelt | 操作系统策略 | 本地集成较好 | macOS Coding Agent |
| Bubblewrap | Linux命名空间 | 轻量、灵活 | 本地受限命令 |
| Docker | Namespace、Cgroups等 | 生态成熟、部署方便 | 受控任务执行 |
| gVisor | 用户态内核隔离层 | 更强的系统调用隔离 | 多租户代码执行 |
| Firecracker MicroVM | 硬件虚拟化 | 较强的虚拟机隔离 | 高风险租户任务 |
| 独立虚拟机 | 虚拟机隔离 | 边界清晰、灵活 | 高隔离要求任务 |
实际选择取决于威胁模型、操作系统、性能要求与维护能力。
我的选型建议
个人本地 Coding Agent:
优先使用产品已经集成的操作系统级Sandbox,不必为了本地任务额外部署复杂的云端执行系统。
企业内部 Agent:
可以从经过安全加固的容器开始,结合权限隔离、资源限制和审计。
面向公共用户的代码执行平台:
建议优先评估gVisor、MicroVM或独立虚拟机,而不是直接把任意用户代码放进普通容器。
涉及生产凭据、金融数据或多租户敏感数据:
应采用独立安全审查的执行环境,并尽可能将高权限业务操作移到沙箱外的可信服务中。
不存在一种对所有场景都最优的Sandbox技术。
七、动手实现:一个最小的 Python Sandbox Runner
下面我们实现一个简单的代码执行器。
它支持:
-
将待运行的Python代码保存到临时工作区。
-
使用Docker启动隔离进程。
-
禁止容器网络访问。
-
以非Root用户运行。
-
限制CPU、内存和进程数量。
-
只读挂载代码。
-
限制执行时间。
-
获取执行结果。
-
在超时后尝试销毁执行容器。
为了安全,这个示例只演示在本地执行测试代码,不开放公网API。
前提条件
需要安装:
-
Python 3.10及以上。
-
Docker Engine或Docker Desktop。
-
已拉取的Python基础镜像。
首先准备镜像:
docker pull python:3.12-slim
在生产环境中,应固定可信镜像的Digest,并对镜像来源和漏洞进行检查,而不是长期依赖浮动Tag。
完整示例
import subprocess
import tempfile
import uuid
from pathlib import Path
IMAGE = "python:3.12-slim"
def run_python_sandbox(
code: str,
timeout: int = 10,
) -> dict:
container_name = "agent-" + uuid.uuid4().hex
with tempfile.TemporaryDirectory() as tmp:
workspace = Path(tmp)
script = workspace / "task.py"
script.write_text(code, encoding="utf-8")
command = [
"docker", "run",
"--rm",
"--name", container_name,
# 不允许访问网络
"--network", "none",
# 只读根文件系统
"--read-only",
# 丢弃Linux Capabilities
"--cap-drop", "ALL",
# 禁止获取额外权限
"--security-opt",
"no-new-privileges=true",
# 限制资源
"--memory", "256m",
"--memory-swap", "256m",
"--cpus", "0.5",
"--pids-limit", "64",
# 非root用户
"--user", "65534:65534",
# 只读挂载任务代码
"--mount",
f"type=bind,src={workspace},"
"dst=/work,readonly",
# 临时可写空间
"--tmpfs",
"/tmp:rw,noexec,nosuid,size=16m",
"--workdir", "/tmp",
IMAGE,
"python", "-B",
"/work/task.py",
]
try:
result = subprocess.run(
command,
capture_output=True,
text=True,
timeout=timeout,
check=False,
stdin=subprocess.DEVNULL,
)
return {
"exit_code": result.returncode,
"stdout": result.stdout[:8192],
"stderr": result.stderr[:8192],
"timed_out": False,
}
except subprocess.TimeoutExpired:
# 尽力清理超时容器
subprocess.run(
[
"docker", "rm",
"-f", container_name
],
capture_output=True,
timeout=5,
check=False,
)
return {
"exit_code": None,
"stdout": "",
"stderr": "Execution timed out",
"timed_out": True,
}
if __name__ == "__main__":
code = """
print("Hello from Agent Sandbox")
print(sum([1, 2, 3, 4, 5]))
"""
result = run_python_sandbox(code)
print(result)
在支持所列资源限制的Docker环境中,预期输出类似:
{
'exit_code': 0,
'stdout': 'Hello from Agent Sandbox\n15\n',
'stderr': '',
'timed_out': False
}
这段代码实现了什么?
首先,它不直接在宿主机的Python环境中执行输入代码。
其次,任务容器无法直接访问网络。
第三,工作目录只读挂载,代码不能直接修改宿主机上的源文件。
第四,容器的CPU、内存和进程数量受到限制。
第五,任务超时后会尝试清理执行环境。
这已经具备了一个基础Sandbox Runner的主要形态。
但这还不是生产级安全沙箱
必须明确这几个限制。
第一,Docker仍然依赖宿主环境的容器隔离能力。 这个示例不能保证抵御容器逃逸或所有内核漏洞。
第二,调用Docker的宿主进程本身具有较高权限。 不能直接把Docker Socket暴露给Agent或不可信容器。生产环境应通过独立受控的Runner服务创建容器。
第三,资源限制不等于完整资源计量。 真实系统还需要控制日志、磁盘、容器总数和任务并发。
第四,超时清理是尽力而为。 如果Docker服务异常或宿主进程意外终止,需要独立的任务清理和回收机制。
第五,单纯设置 --network none 不能替代完整的多租户隔离。
因此,这个示例适合教学、原型和受控的本地测试。
如果要面对大量陌生用户的任意代码,仍应进一步采用强隔离运行时,并进行专业安全评估。
八、为什么不建议让 Agent 直接执行任意 Shell 命令?
很多 Coding Agent 的最初实现非常简单:
subprocess.run(
command,
shell=True
)
这里的 command 直接来自模型输出。
这种写法虽然方便,却很容易引入风险。
例如:
模型可能生成包含多个连续操作的命令。
它也可能错误地拼接文件路径。
更严重的是,工具返回的不可信文本可能影响模型生成下一条命令。
如果执行程序没有任何隔离,那么模型生成的Shell命令就可能获得运行服务的全部权限。
更合理的执行方式
建议拆成三个部分:
Command Planner
模型负责提出操作意图。
Execution Policy
可信代码检查操作类别、工作区权限和风险级别。
Sandbox Executor
在受限环境中执行实际操作。
例如:
LLM
|
v
Proposed Command
|
v
Policy Engine
|
+---- Denied
|
+---- Approval Required
|
v
Sandbox Executor
|
v
Execution Result
尤其要避免将Shell命令字符串作为唯一的安全控制对象。
对于文件读取、代码搜索、测试执行等常见操作,可以设计更具体的工具接口。
例如:
read_project_file
search_repository
run_unit_tests
apply_patch
这通常比让模型始终调用一个无限制的 run_shell 工具更容易治理。
但即使使用专用工具,也需要防范其内部执行的子进程和依赖代码。
九、长任务运行时:Sandbox 与任务状态如何协同?
一个真正的Coding Agent,执行时间可能从几秒延长到几十分钟。
例如:
“分析整个仓库,修复测试失败,并生成最终补丁。”
执行过程中可能发生:
-
模型请求超时。
-
沙箱进程崩溃。
-
依赖安装失败。
-
任务被用户取消。
-
网络暂时不可用。
-
Agent等待人工审批。
-
执行环境被回收。
因此,Agent Runtime 不能只维护一段聊天历史。
它还需要维护真实执行状态。
建议的任务状态机
CREATED
|
v
QUEUED
|
v
RUNNING
|
+------+-------+
| | |
v v v
PAUSED FAILED COMPLETED
| |
v v
RESUMED RETRYING
| |
+------+
|
v
RUNNING
此外,RUNNING状态下也需要支持用户取消操作。
Checkpoint 并不等于环境快照
这是一个特别容易被忽略的问题。
假设Agent已经完成了以下动作:
-
修改三个代码文件。
-
安装依赖。
-
运行部分测试。
-
保存Checkpoint。
如果执行环境被销毁,只恢复模型消息历史,并不能保证任务真正恢复。
原因是文件系统可能已经回到初始状态。
临时安装的依赖也可能消失。
因此,需要分别处理:
Logical Checkpoint: 模型上下文、执行计划、任务进度和工具状态。
Workspace State: 文件修改、代码版本、构建产物和运行环境。
External Side Effects: 已经创建的Pull Request、提交的API请求和修改的外部数据。
这三类状态不能简单混为一谈。
对于Coding Agent,可以将代码变更保存为Patch或Git Commit,再结合执行Checkpoint恢复。
对于业务Agent,则需要使用任务ID、幂等键和外部状态核验。
推荐的恢复原则
任务重新启动时:
首先验证工作区版本。
然后恢复已经确认的修改。
检查此前工具调用是否已经产生副作用。
最后再让模型决定下一步操作。
不要直接把整个任务从头重新运行。
否则,重复执行可能产生不一致结果,甚至引发重复操作。
十、Agent Runtime 如何保护密钥?
在真实项目中,Agent经常需要访问:
-
GitHub仓库。
-
云服务API。
-
数据库。
-
软件包仓库。
-
自动化测试系统。
-
企业内部工具。
这些服务可能需要身份认证。
但一个常见错误,是直接把生产环境密钥放进Sandbox的环境变量中。
例如:
DATABASE_PASSWORD=...
GITHUB_TOKEN=...
CLOUD_API_KEY=...
当Agent能够执行任意代码时,这些凭据很可能变成代码可访问的资源。
即使使用了Docker,也不意味着凭据自动受到保护。
我推荐的三层设计
第一层:Sandbox不直接持有生产密钥。
大多数测试和代码分析任务,不应该访问真实生产环境。
第二层:需要外部服务时,通过可信代理。
例如,Agent请求创建Pull Request。
不是让Agent拿到完整GitHub Token,而是让它调用一个经过授权的 create_pull_request 服务。
服务端负责验证仓库、分支、操作范围和用户权限。
第三层:必要时使用短期、最小权限凭据。
如果确实需要在执行环境中使用凭据,应尽量采用短生命周期和受限权限。
同时确保任务结束后能够撤销相关凭据。
OpenAI当前自托管执行环境文档也强调了应用管理密钥和执行环境密钥的分离。
这体现了一个重要原则:
执行代码需要的权限,不应该自动等于管理整个平台的权限。
十一、如何设计生产级 Agent Sandbox 平台?
如果要建设一个支持多个用户同时运行任务的Coding Agent平台,我建议采用分离式架构。
Client / API
|
v
Agent Service
|
Task Scheduler
|
v
Runtime Manager
|
+------------+------------+
| | |
v v v
Context Memory Checkpoint
| | |
+------------+------------+
|
v
Tool Gateway
|
Sandbox Manager
|
+-------------+-------------+
| | |
v v v
Sandbox A Sandbox B Sandbox C
User A User B User C
| | |
+-------------+-------------+
|
v
Artifact Store
|
v
Verification Runner
|
v
Audit & Evals
核心组件
Agent Service
负责接收任务、用户鉴权与模型交互。
Task Scheduler
负责排队、并发限制和资源调度。
Runtime Manager
负责Agent Loop、任务状态、超时和取消。
Sandbox Manager
负责隔离环境的创建、生命周期和销毁。
Artifact Store
负责存储代码补丁、测试报告和其他任务产物。
Verification Runner
在必要时使用独立、干净的环境重新验证结果。
Audit & Evals
记录任务成功率、失败原因、资源消耗和安全策略执行结果。
为什么需要独立的 Verification Runner?
因为Agent自己报告“测试通过”,不应该成为最终验收依据。
尤其对于复杂任务,Agent运行环境可能经历多次修改。
它的依赖、缓存或临时文件状态可能影响测试结果。
因此,一个更可靠的设计是:
Agent完成修改后,输出代码Patch。
然后由独立的验证环境应用Patch并运行测试。
只有独立验证通过,才能提高对结果的信任程度。
这实际上将第六篇的Sandbox与第四篇的Agent Evals联系了起来。
十二、怎样评测一个 Sandbox 是否有效?
很多团队部署完容器之后,就认为安全建设已经完成。
但一个未经验证的Sandbox,不应该直接用于执行高风险代码。
至少需要建立独立的Sandbox Evals。
1. 文件隔离测试
验证容器能否读取授权工作区之外的文件。
验证是否可以通过符号链接、挂载点等方式访问非授权目录。
2. 网络隔离测试
验证网络默认禁止是否生效。
如果配置白名单,需要验证非授权目标是否被拒绝。
3. 权限提升测试
验证受限进程不能获取不必要的系统权限。
验证容器中不会意外暴露宿主机管理接口。
4. 资源耗尽测试
验证无限循环、内存过度分配、大量进程创建等情况能否被限制和终止。
5. 密钥保护测试
验证执行环境不能读取不属于当前任务的凭据。
6. 多租户隔离测试
验证用户A的任务不能读取用户B的工作区、缓存和任务产物。
7. 任务恢复测试
验证沙箱异常退出后,任务能够恢复到正确状态,不会重复执行有副作用的操作。
建议的评测矩阵
| 测试项目 | 期望结果 |
|---|---|
| 写入授权工作区 | 按策略允许 |
| 访问其他用户目录 | 拒绝 |
| 网络访问非授权地址 | 拒绝 |
| 读取平台管理密钥 | 拒绝 |
| 超过CPU配额 | 受到限制 |
| 超出内存限制 | 执行失败或被终止 |
| 超时任务 | 停止并清理 |
| 未审批权限提升 | 拒绝 |
| 任务异常重启 | 可恢复或安全失败 |
| 执行环境销毁 | 临时数据按策略清除 |
这里需要注意:
安全评测不能只是让模型回答“我不会访问这些资源”。
必须通过实际执行结果,验证系统有没有阻止越权行为。
十三、Agent Sandbox最容易犯的五个错误
错误一:把Docker等同于完整安全隔离
Docker是一种重要的基础设施,但默认容器配置并不自动满足高风险、多租户不可信代码执行要求。
特别要避免随意使用 --privileged 或暴露Docker Socket。
错误二:只隔离文件系统,不隔离网络
即使文件访问受到限制,如果容器可以自由访问外部服务,仍然可能产生数据泄露和网络攻击风险。
文件系统与网络策略必须共同设计。
错误三:把生产密钥放进执行环境
当Agent可以执行任意代码时,不能假设环境变量中的密钥对它不可见。
应该把敏感操作移交给可信业务服务。
错误四:只有超时,没有资源限制
10秒超时并不意味着10秒内不会耗尽系统资源。
CPU、内存、进程和存储都需要独立限制。
错误五:允许Agent绕过Sandbox来解决问题
有些系统为了提高任务成功率,会允许模型在遇到权限问题时切换到完全不受限的执行模式。
这种方式可能在短期内提升任务完成率,却破坏了安全模型。
更合理的做法是让用户明确批准特定权限,或者提供专门受控的替代工具。
解决Sandbox限制的方法,不应该是默认取消Sandbox。
十四、未来的 Agent Runtime 会如何发展?
我认为有三个方向值得关注。
1. Runtime 将越来越重视任务生命周期
早期Agent主要围绕一次对话运行。
未来Agent需要执行持续数小时甚至跨越多天的任务。
因此,Checkpoint、任务恢复、事件日志、审批和执行环境管理会成为基础能力。
2. Sandbox 会从附加功能变成默认基础设施
随着Agent拥有更多工具权限,单纯依赖用户批准每一步的方式越来越难以满足体验和安全需求。
更可能的发展方向是:
定义安全边界,让Agent在边界内自由执行。
只有当任务确实需要越界时,才要求额外授权。
3. 执行环境将根据任务风险动态分级
不是所有任务都需要昂贵的MicroVM。
例如:
简单文本解析可以运行在受控应用进程中。
普通代码测试可以使用加固容器。
陌生代码或高风险任务可以使用更强的虚拟化隔离。
这意味着未来的Sandbox Manager可能需要根据任务类型、用户权限和环境信任等级选择不同的执行后端。
但这种动态分级必须由可信策略决定,而不是让模型自行宣称任务风险较低。
十五、回到这个系列:Agent工程化已经形成完整闭环
到目前为止,我们已经讨论六个核心主题。
第一篇,Harness Engineering。
解决Agent如何组织和控制执行。
第二篇,Context Engineering。
解决Agent在每次推理中应该获得什么信息。
第三篇,Memory Engineering。
解决Agent如何保存和复用长期经验。
第四篇,Agent Evals。
解决怎样验证Agent是否真正变好了。
第五篇,Tool Calling与MCP。
解决Agent如何调用外部工具,以及如何控制工具权限。
今天的第六篇,Runtime与Sandbox。
解决Agent如何安全执行代码,以及怎样限制错误行动的影响范围。
把这六个部分组合起来,可以得到:
用户任务
|
v
Agent Harness
|
+----------+----------+
| |
v v
Context Memory
| |
+----------+----------+
|
v
LLM
|
v
Tool Gateway
|
Authorization
|
v
Agent Runtime
|
Sandbox Manager
|
+----------+----------+
| | |
v v v
Filesystem Network Resources
| | |
+----------+----------+
|
v
Tool Execution
|
v
Verification
|
v
Evals
|
v
Improvement Loop
这已经不再是一个简单的聊天机器人架构。
而是一套能够处理信息、执行任务、限制风险、恢复状态和持续改进的智能软件系统。
结语:真正可靠的Agent,不需要被完全信任
当AI开始编写代码、运行Shell、安装依赖和操作外部系统时,我们不能再把它仅仅当作一个生成文本的模型。
它已经成为软件系统中的行动主体。
而任何能够产生实际影响的行动主体,都应该受到明确的权限边界约束。
未来优秀的 Agent Runtime,不只是让Agent运行得更快、调用更多工具、完成更复杂的任务。
更重要的是,它应该能够回答:
Agent能够访问什么?
Agent不能访问什么?
代码运行失败后怎么办?
执行环境出现异常时怎么办?
任务是否可以恢复?
如果模型受到恶意内容影响,实际执行范围能否被限制?
如果用户授权了一个任务,系统是否会错误地扩大这份授权?
这些问题不能只依赖Prompt,也不能只依赖模型的安全判断。
它们需要操作系统隔离、可信权限系统、执行调度、资源管理、状态恢复和客观验证共同解决。
Sandbox的价值,不是保证Agent永远不会犯错,而是让错误受到约束,让自主执行建立在可信边界之上。
当我们能够做到这一点,Agent才能真正从一个会调用工具的AI助手,成长为可以安全参与真实软件开发和业务流程的执行系统。
未来值得信任的Agent,不是拥有无限权限的Agent,而是在有限权限内持续可靠完成任务的Agent。
- 点赞
- 收藏
- 关注作者
评论(0)