你的 Agent 是个黑箱:eBPF 如何看透它真正在做什么

时间:2026-07-06 08:27:40 来源:互联网

近期曝出的TrapDoor攻击手法显示,攻击者将零宽Unicode字符植入.cursorrules文件中,Agent在读取后便会自动遍历文件系统并外发密钥。紧随其后的Miasma Wave 2攻击则更进一步,它将后门配置文件直接放入项目目录,当用户克隆仓库并打开项目时,后门即被激活。整个过程既无弹窗提醒,也没有任何告警信息,甚至连沙箱环境也无法触发检测。

所有攻击行为都严格发生在授权边界之内,Agent仅仅是“按照配置工作”。

现有的防御措施大多聚焦于解决“安装前”的问题,例如扫描依赖、审核注册表以及提醒用户仅安装可信来源。然而,一旦恶意配置成功进入你的环境并开始运行,Agent实际在做什么,便无人知晓。

img_6a4af67cb982430.webp

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

为了清晰地理解Agent的可观测性,可以将其划分为一个分层模型,具体包含三个层次:

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

L1 日志层是你最熟悉的层面,包括Claude Code的标准输出、LangChain的回调函数以及你自己添加的日志。然而,这一层的核心问题是不可信。一旦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稳定,适合执行策略

前两种钩子让你能够“看见”系统行为,第三种钩子则允许你“拦住”潜在风险。针对Agent的可观测性,tracepoints适合长期监控,kprobes用于按需审计,而LSM hooks则提供实时阻断能力。三者配合,你就能在系统边界建立起完整的控制面。

eBPF能够观测到每一个关键系统调用:

  1. openat2 —— 读取了什么文件
  2. connect —— 连接了哪个IP地址
  3. execve —— 启动了哪个子进程
  4. sendto/recvfrom —— 网络流量的具体细节

重要的是,这一切操作Agent完全无感知。你无需修改Agent的一行代码,也无需安装任何sidecar,而性能开销仅为1-3%的CPU。

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

理论讲解完毕,现在我们直接进行实践。

1. 安装 bpftrace

 复制代码sudo apt-get install -y bpftrace

以下这段脚本可以在kernel 5.8+版本上实时打印出Claude Code进程所打开的文件:

 复制代码sudo bpftrace -e '
tracepoint:syscalls:sys_enter_openat {
  if (comm == "claude") {
    printf("OPEN: pid=%d, file=%sn", 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. 若要抓取数据传输(例如sendrecv),需要进行更复杂的内核结构体解析,仅靠一行脚本无法完成。

对于生产环境的网络监控,推荐使用下文介绍的Tetragon配合TracePolicy,或者直接使用ss -tunap | grep <进程名>命令来查看已建立的连接。

2. 生产环境:Tetragon

bpftrace更适合临时审计。如果你需要长期监控,特别是在Kubernetes环境中运行的Agent,那么Tetragon是更合适的选择。它通过eBPF实现内核级追踪,原生支持Pod、Namespace和Label的关联,并可通过TracePolicy实现进程级阻断。

这里需要澄清一个容易混淆的点:bpftrace只能用于观测,无法进行阻断。它适用于临时审计和快速验证,但在生产环境中进行执行策略拦截时,则需要Tetragon的TracePolicy(支持进程级阻断)或KubeArmor的LSM策略。Falco则仅提供检测功能,不进行拦截。

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

假设你的客服Agent收到一个包含间接提示注入的工单。这个注入指令覆盖了任务上下文,导致Agent从PII表中拉取数据,并将其POST到一个外部端点。

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

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

检测层能看到什么漏掉什么
eBPF/kernel检测到新的TCP连接至未知IP地址,DNS解析到不明域名,数据库socket读取量出现异常。无法知晓建立这个连接的原因,无法判断数据库查询是否合法,更无法确认这是否由提示注入触发。
容器运行时未发现镜像漂移,未发现意外进程,可能观察到网络出口流量峰值。无法区分出口流量是合法数据传输还是数据外泄,缺乏完整的因果链。
K8s 控制面无异常发现。RBAC未变、SA未变、API Server也未变。一切异常都被遗漏。因为攻击完全在授权边界内完成。
应用层 L7 + tool能够看到输入流中的注入提示,检测到针对新表的未授权数据库Tool调用,发现包含PII数据的POST请求发往未知域名,并能构建完整的因果链:工单导致数据外泄。几乎没有遗漏。这是唯一拥有完整上下文信息的层面。

这个表格说明了两件事:第一,K8s和容器运行时在这个场景下几乎失效,因为攻击无需逃逸和提权,完全在授权边界内进行。第二,eBPF虽然能捕捉到异常信号,但它无法区分“合法的新行为”和“恶意攻击行为”。

这就是看到不等于理解的根本原因。eBPF知道Agent在14:23:05连接了一个陌生IP,并读取了一块数据库区域,但它无法知晓:

  1. 这个连接是因为提示注入触发的
  2. 数据库查询读取的是PII数据还是普通数据
  3. Agent的“意图”到底是什么

这正是UC Berkeley的AgentSight论文(arXiv:2508.02736)中提出的“语义鸿沟”概念:

  1. 意图流(Intent stream):Agent在与LLM通信中表达的意图。即使流量是TLS加密的,也可以在SSL_readSSL_write函数上挂载uprobe来截获解密后的内容。
  2. 动作流(Action stream):Agent实际执行的一系列系统调用。
  3. 两者之间的断层:内核知道动作,但不知道意图;LLM通信中包含意图,但如果没有关联机制,这些意图就是孤立的文本。

AgentSight的核心创新在于构建了一个因果关联引擎,它将“某个时间点LLM输出了什么意图”与“之后N秒内发生了哪些系统调用”实时关联起来,并利用一个副LLM进行语义分析,从而判断行为是否偏离了预期。

该论文报告的开销低于3%,其代码已在GitHub上开源,包含Rust 6000行和TypeScript 3000行前端代码。

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

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

原因在于,AI Agent的行为模式是不确定的

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

然而,Agent的行为由提示词决定。同一个Agent,上午的任务可能是“分析销售数据”,下午的任务就变成了“爬取竞品信息”。前者可能只读取本地CSV文件,而后者则可能需要连接几十个外部域名。静态白名单要么设置得太宽松起不到作用,要么设置得太严格导致频繁误报,从而打断Agent的正常工作。

我们先来看一下截止2026年6月,一些开源工具的适用性:

工具类型Agent 场景适用性Overhead
Cilium Tetragon (v1.7+)运行时安全 + 执行策略中等——该工具支持K8s,并通过TracePolicy CRD实现阻断。最低(采用内核过滤)
Falco (v0.40+)运行时安全(仅检测)低——该工具仅能检测,无法阻断,且规则是静态的。中低
Tracee (v0.23+)深度系统调用追踪低——其开销较高,是Tetragon的2到4倍,适合调试环境而非生产环境。
KubeArmor (v1.4+)强制访问控制中等——该工具基于LSM,支持文件、网络和进程策略。中低

Tetragon适合用于建立Agent行为基线以及进行异常检测,Falco适用于安全审计与合规场景但无法实时阻断,Tracee的深度足够但开销太高不适合生产环境。它们对于确定性工作负载很有效,但Agent并没有一个稳定的系统调用配置文件。

这些工具本身不连接LLM。Tetragon和KubeArmor是规则驱动的:你编写YAML文件来定义“检测到X就拦截”,其执行是确定性的,没有LLM参与。这与AgentSight那种“使用副LLM进行语义分析”的方案是两条完全不同的路线。

那么,LLM在阻断链路中能做什么呢?目前来看,有三类方案,但没有任何一种方案是“由LLM实时推理并拦截系统调用”的:

方案类型代表项目LLM 角色实时性
LLM 生成规则,规则引擎执行AgentSpec (ICSE 2026)、SafeClaw-RLLM离线生成安全策略或DSL规则。 毫秒级执行
LLM 分析异常,人工/异步响应AgentSight、ARMOLLM关联意图流和动作流,判断行为是否偏离。 告警后响应
权限框架,deny-by-defaultSkillGuard基于技能清单预定义权限边界。 实时

AgentSpec论文的关键结论是:“LLM作为判断者缺乏可靠的实时执行能力”——LLM做判断的速度太慢且结果不一致,系统调用级别的拦截无法承受几百毫秒的推理延迟。因此,现实的架构是LLM离线生成规则,再由轻量级引擎实时执行

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

通过对比可以更清晰地理解这一点:

维度通用 eBPF(Tetragon/Falco)AI-aware eBPF(ARMO)
策略模型静态白名单加规则。动态策略,基于行为基线进行演化。
检测上下文系统调用级别的异常。结合系统调用、应用层Tool调用以及L7流量内容。
策略粒度按Pod或Namespace划分。按单个Agent划分,反映各自的行为画像。

另一个值得关注的方案是groundcover(2026年)。他们在K8s集群中运行eBPF传感器,自动识别OpenAI、Anthropic等提供商的流量,并将LLM调用转换为OTel Trace。提示词、响应、Token用量和延迟等信息都被记录为Span,无需SDK埋点。该方案甚至还提供了一个MCP Server,让Agent可以自己查询观测数据。

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

五、eBPF 不是银弹

写到此处必须坦诚地说:eBPF解决的是“看见”的问题,而不是“理解”的问题。

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

  1. 应用层上下文:这个连接的HTTP请求体里包含什么内容?这需要L7探针或像AgentSight那样的TLS截获功能。
  2. 业务语义:这个IP地址是否在白名单中?这次数据读取是否符合当前的任务目标?这需要对接你的业务系统。
  3. 因果链:这个行为是由哪个用户请求或哪条提示词触发的?这需要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虽然不是银弹,但它至少能让你看见以前看不见的东西。


参考资料

  1. AgentSight(UC Berkeley,arXiv:2508.02736): arxiv.org/html/2508.0…
  2. ARMO:eBPF for AI Agent Enforcement: www.armosec.io/blog/ebpf-b…
  3. groundcover:AI Agent Observability: www.groundcover.com/learn/obser…
  4. Tetragon: tetragon.io
  5. Futurum 2026调研:AI Agent可观测性进入企业采购优先级Top 10