沙箱防逃逸,审批防越权,但 Agent 拿到合法权限后的行为——没人看得见。
本文首发地址 https://h89.cn/archives/625.html

上个月披露的 TrapDoor 攻击,攻击者在 .cursorrules 里埋零宽 Unicode 字符,Agent 读取后自动遍历文件系统外发密钥。这个月 Miasma Wave 2 更进一步——后门配置文件直接丢进项目目录,你克隆仓库、打开项目,后门就激活了。

没有弹窗,没有告警,沙箱也不触发。攻击完全发生在授权边界内,Agent 只是"按配置工作"。

所有防御措施都在解决"安装前"的问题:扫描依赖、审核 registry、提醒用户只装可信来源。但一旦恶意配置进了你的环境,Agent 开始运行之后——它实际在做什么,没人知道。

封面

一、三层观测:从"它说了什么"到"它做了什么"

我画了一个分层模型,把 Agent 可观测性拆成三层:

L1: Agent 日志层 —— "它打算做什么"
L2: OTel 链路层 —— "它调了什么 API"
L3: eBPF 内核层 —— "它实际做了什么"

L1 日志层就是你最熟悉的:Claude Code 的 stdout、LangChain 的 callback、你自己打的 log。这一层的问题是不可信——Agent 被注入控制后,可以选择性报告,甚至伪造日志。

L2 链路层用 OpenTelemetry 追踪 Agent → LLM → Tool 的调用链,记录 token 用量、耗时、成本。这一层比 L1 客观,但它只能看到"应用层约定好的交互",看不到进程内部实际读了哪些文件、连了哪些 IP。

L3 eBPF 内核层才是本文的重点。eBPF 是 Linux 内核的沙盒运行时,让你在不改内核、不装内核模块的情况下,在内核态执行自定义程序。它通过三种钩子接入系统:

类型 用途 稳定性
kprobes/kretprobes 动态探针,挂载到任意内核函数(tcp_connectdo_sys_open 非稳定 ABI,内核升级可能失效
tracepoints 稳定检测点(sched_process_execsys_enter_*),永不过期 稳定,适合长期部署
LSM hooks 强制访问控制层,可在操作完成前拒绝(bpf_lsm_file_open 稳定,适合 enforcement

前两种让你"看见",第三种让你"拦住"。对于 Agent 可观测性,tracepoints 做长期监控,kprobes 做按需审计,LSM hooks 做实时阻断——三者配合,你在系统边界就有了完整的控制面。

它能看到的每个系统调用:

  • openat2 —— 读了什么文件
  • connect —— 连了哪个 IP
  • execve —— 启动了什么子进程
  • sendto/recvfrom —— 网络流量细节

而且Agent 完全无感知——不需要改一行 Agent 代码,不需要装什么 sidecar,开销只有 1-3% CPU。

二、实操:用 bpftrace 看 Claude Code 在干什么

理论讲完,直接上手。

1. 安装 bpftrace

sudo apt-get install -y bpftrace

以下这段脚本,可以实时打印 Claude Code 进程打开的文件(在 kernel 5.8+ 上测试通过):

sudo bpftrace -e '
tracepoint:syscalls:sys_enter_openat {
  if (comm == "claude") {
    printf("OPEN: pid=%d, file=%s\n", pid, str(args->filename));
  }
}'

跑起来之后,你在另一个终端正常用 Claude Code 工作,这边就会实时输出:

OPEN: pid=8842, file=/home/user/.claude/settings.json
OPEN: pid=8842, file=/home/user/project/src/main.rs
OPEN: pid=8842, file=/home/user/project/.env

关键点是——这个信息是内核直接报告的,不经过 Claude Code 的日志系统。即使 Claude Code 被注入了"不要记录文件访问"的指令,内核依然会如实上报。

网络监控为什么不在这里展示?

实际测试发现,用 bpftrace 抓网络连接有两个问题:

  1. 现代 Agent 大多使用长连接/连接池,启动时就建好了,connect() 系统调用很少触发
  2. 如果要抓数据传输(send/recv),需要更复杂的内核结构体解析,一行脚本搞不定

生产环境的网络监控,推荐用下面介绍的 Tetragon + TracePolicy,或者直接用 ss -tunap | grep <进程名> 查看已建立的连接。

想监控 OpenCode?把 comm == "claude" 改成 comm == "opencode" 即可。进程名可以通过 ps aux | grep <你的Agent> 查看。

2. 生产环境:Tetragon

bpftrace 适合临时审计。如果要长期监控,特别是 K8s 环境里跑 Agent,用 Tetragon 更合适——它通过 eBPF 做内核级追踪,原生支持 pod/namespace/label 关联,还能用 TracePolicy 做进程级阻断。

这里需要澄清一个容易混淆的点:bpftrace 只能观测,不能阻断。它适合临时审计和快速验证,但生产环境要做 enforcement(拦截),需要 Tetragon 的 TracePolicy(支持进程级阻断)或 KubeArmor 的 LSM 策略。Falco 检测-only,不拦截。

三、语义鸿沟:eBPF 知道"它做了什么",但不知道"为什么做"

假设你的客服 Agent 收到一个含间接 prompt injection 的工单。注入指令覆盖任务上下文,让 Agent 从 PII 表拉数据,POST 到一个外部端点。

我们用这个实际攻击场景来说明不同检测层的能力边界:

不同检测层的能力边界对比

检测层 能看到什么 漏掉什么
eBPF/kernel 新 TCP 连接到未知 IP。DNS 解析到不明域名。数据库 socket 读取量异常。 为什么建立这个连接。数据库查询是否合法。是不是 prompt injection 触发的。
容器运行时 无镜像漂移。无意外进程。可能的网络出口流量峰值。 出口流量是合法数据传输还是外泄。无因果链。
K8s 控制面 无。RBAC 不变、SA 不变、API server 不变。 一切。攻击在授权边界内完成。
应用层 L7 + tool 输入流中的注入 prompt。针对新表的未授权数据库 tool 调用。含 PII 的 POST 到未知域名。完整的因果链:工单→外泄。 几乎没有。这是拥有完整上下文的一层。

这个表说明两件事:第一,K8s 和容器运行时在这个场景下几乎失明——攻击不需要逃逸、不需要提权,完全在授权边界内完成。第二,eBPF 能捕捉到异常信号,但无法区分"合法新行为"和"攻击行为"。

这就是看到不等于理解。eBPF 知道 Agent 在 14:23:05 连了一个陌生 IP、读了一块数据库区域,但它不知道:

  • 这个连接是因为 prompt injection 触发的
  • 数据库查询读取的是 PII 还是普通数据
  • Agent 的"意图"是什么

这就是 UC Berkeley 的 AgentSight 论文(arXiv:2508.02736)里提出的"语义鸿沟"(Semantic Gap):

  • Intent stream(意图流):Agent 在 LLM 通信中表达的意图——即便流量是 TLS 加密的,也可以在 SSL_read/SSL_write 挂 uprobe 截获解密后的内容
  • Action stream(动作流):Agent 实际执行的系统调用
  • 两者之间的断层:内核知道动作,但不知道意图;LLM 通信里有意图,但如果没有关联机制,它就是孤立文本

AgentSight 的核心创新就是做了一个因果关联引擎:把"某个时间点 LLM 输出了什么意图"和"之后 N 秒内发生了哪些系统调用"实时关联,再用一个副 LLM 做语义分析,判断行为是否偏离预期。

论文报告的 overhead 不到 3%。代码开源在 GitHub,Rust 6000 行 + TS 3000 行前端。

四、为什么通用安全工具不够:AI Agent 没有稳定行为基线

你可能会问:既然 eBPF 能监控进程行为,那直接用 Falco、Tetragon 这些成熟工具不就行了?为什么还要专门搞"AI-aware"的方案?

因为 AI Agent 的行为不是确定的

一个 Web 服务器的行为是可预测的:它监听 80/443,读写特定目录,连特定的数据库和缓存。你给 Falco 写一条规则:"除了连 redis:6379 和 postgres:5432 之外的网络连接都告警",这完全可行。

但 Agent 的行为由 prompt 决定。同一个 Agent,上午的任务是"分析销售数据",下午的任务是"爬取竞品信息"。前者可能只读本地 CSV,后者可能要连几十个外部域名。静态白名单要么太松(等于没设),要么太紧(频繁误报打断 Agent 正常工作)。

先看开源工具的适用性(截至 2026-06):

工具 类型 Agent 场景适用性 Overhead
Cilium Tetragon (v1.7+) 运行时安全 + enforcement 中等——K8s-aware,支持 TracePolicy CRD,可阻断 最低(in-kernel 过滤)
Falco (v0.40+) 运行时安全(检测-only) 低——检测-only,不阻断,静态规则 中低
Tracee (v0.23+) 深度系统调用追踪 低——overhead 高(2-4x Tetragon),适合调试非生产
KubeArmor (v1.4+) 强制访问控制 中等——LSM-based,支持 file/network/process 策略 中低

Tetragon 适合 Agent 行为基线建立 + 异常检测,Falco 适合安全审计 + 合规但无法实时阻断,Tracee 深度足够但 overhead 太高不适合生产。它们对确定性工作负载有效,但 Agent 没有稳定的 syscall profile。

这些工具本身不接 LLM。Tetragon 和 KubeArmor 是规则驱动的——你写 YAML 定义"检测到 X 就拦截",执行是确定性的,没有 LLM 参与。这和 AgentSight 那种"用副 LLM 做语义分析"是两条完全不同的路线。

那 LLM 在阻断链路里能干什么?目前看有三类方案,但没有一个是"LLM 实时推理拦截系统调用"的:

方案类型 代表项目 LLM 角色 实时性
LLM 生成规则,规则引擎执行 AgentSpec (ICSE 2026)、SafeClaw-R LLM 离线生成安全策略/DSL 规则 ✅ 毫秒级执行
LLM 分析异常,人工/异步响应 AgentSight、ARMO LLM 关联意图流和动作流,判断偏离 ❌ 告警后响应
权限框架,deny-by-default SkillGuard 基于 skill manifest 预定义权限边界 ✅ 实时

AgentSpec 论文的关键结论:"LLM-as-a-Judge lack reliable real-time enforcement"——LLM 做判断太慢且不一致,系统调用级别的拦截等不起几百毫秒的推理延迟。所以现实架构是LLM 离线生成规则 + 轻量级引擎实时执行

ARMO 在 2026 年 3 月的一篇博客里提出了一个概念叫 Application Profile DNA——不是记录"Agent 通常做什么"的静态快照,而是记录"Agent 在不同任务下的行为分布",并随时间演化。

对比一下就清楚了:

维度 通用 eBPF(Tetragon/Falco) AI-aware eBPF(ARMO)
策略模型 静态白名单 + 规则 动态策略,基于行为基线演化
检测上下文 系统调用级异常 syscall + 应用层 tool 调用 + L7 流量内容
策略粒度 按 pod/namespace 按 Agent 个体,反映各自行为画像

另一个值得关注的方向是 groundcover(2026)。他们在 K8s 集群里跑 eBPF sensor,自动识别 OpenAI/Anthropic 等 provider 的流量,把 LLM 调用转成 OTel trace——prompt、响应、token 用量、延迟全部记录为 span,无需 SDK 埋点。甚至还提供 MCP Server,让 Agent 自己 query 观测数据。

这个思路的本质是:不要试图用规则预测 Agent 会做什么,而是观察它实际做了什么,然后问"这偏离正常模式多远"。

五、eBPF 不是银弹

写到这里必须诚实:eBPF 解决的是"看见"的问题,不是"理解"的问题。

它能告诉你 Agent 在 14:23:05 连了 104.18.32.47:443,但它不能告诉你这个连接是正常 API 调用还是数据外泄。要做出这个判断,你需要:

  1. 应用层上下文:这个连接的 HTTP body 里是什么?(需要 L7 探针或 AgentSight 那样的 TLS 截获)
  2. 业务语义:这个 IP 是否在白名单里?这次数据读取是否符合当前任务?(需要对接你的业务系统)
  3. 因果链:这个行为是由哪个用户请求、哪条 prompt 触发的?(需要 OTel 链路追踪)

所以正确的架构是三层叠加,不是单层替代:

┌─────────────────────────────────────────┐
│ L1: Agent 日志(自报告,不可信)          │
├─────────────────────────────────────────┤
│ L2: OTel 链路(API 调用链,不完整)       │
├─────────────────────────────────────────┤
│ L3: eBPF 内核(内核视角,无上下文)       │
└─────────────────────────────────────────┘

L1 给你业务语义,L2 给你调用链,L3 给你不可抵赖的系统行为证据。三者交叉验证,才能回答那个真正重要的问题:Agent 有没有做它不该做的事?

对了,Futurum 2026 年初的调研显示,AI Agent 可观测性已经进入了企业采购优先级的 Top 10。不是因为 CFO 们突然关心新技术,而是因为第一批在生产环境跑 Agent 的团队,已经踩过坑了。

如果你现在就想动手

  1. 快速验证:装一个 bpftrace,跑上面的脚本,看看你的 Agent 实际在做什么
  2. 建立基线:用 Tetragon 在测试环境跑 1-2 周,记录 Agent 的行为分布
  3. 打通三层:把 L1 日志、L2 OTel、L3 eBPF 三层联动起来,交叉验证异常行为

eBPF 不是银弹,但它至少让你看见了之前看不见的东西。


参考资料


本文链接:你的 Agent 是个黑箱:eBPF 如何看见它真正在做什么 - https://h89.cn/archives/625.html

版权声明:原创文章 遵循 CC 4.0 BY-SA 版权协议,转载请附上原文链接和本声明。

标签: Agent, eBPF, claude

🎓 呈言英语 智能英语学习平台
📚单词学习 🎧听说练习 📖阅读理解 ✏️拼写练习 🌟 AI智能推荐 · 科学记忆曲线
🚀 立即开始免费学习

添加新评论