2026年6月30日 2 分钟阅读

Trajeckt 场景实战:当 AI Agent 的多步工具调用变成数据泄露通道

tinyash 0 条评论

问题的起点

想象一个真实场景:你给 AI Agent 配置了访问数据库和发送邮件的权限。单看每个权限——读数据库是合法的,发邮件也是合法的。但 Agent 先读取了用户信息表,然后通过邮件发送出去——这就是一次完整的数据泄露。

传统的安全工具会检查每次工具调用是否合法,发现「读数据库」允许、「发邮件」也允许——两者单独看都没问题。问题出在顺序和组合上:孤立检查每个动作无法发现多步调用中的数据泄露路径。这个安全盲区是所有 tool-calling Agent 的共同隐患。

6 月 29 日,Hacker News 上发布了一个名为 Trajeckt 的开源项目,专门解决这个问题。它的核心理念很简单:不是在 Agent 运行时拦截单个工具调用,而是在 Agent 运行前声明允许的「行为轨迹」,然后在整个会话中强制执行这个轨迹

问题对比:为什么每个动作都检查还不够

维度传统检查(单步)Trajeckt(轨迹级)
检查粒度每个工具调用独立评估整个调用序列跨步骤追踪
数据流感知无—不知道数据从哪个工具流向哪个工具有—追踪敏感数据是否到达禁止出口
多步泄露检测❌ 无法检测「读取→传输」链✅ 检测并阻断「敏感读取→外部写入」路径
绕过难度低—只需让每一步看起来合法高—需要伪造完整的因果轨迹
延迟开销无(直接转发)~1.6ms 每次工具调用

快速上手:体验核心能力

Trajeckt 提供了最简洁的入门方式——一个 Docker Compose 命令就能启动完整的 enforcement 环境:

git clone https://github.com/beebeeVB/trajeckt
cd trajeckt
docker-compose up --build

首次构建需要几分钟(编译 Rust 代码),之后启动只需数秒。启动后验证:

curl -s http://localhost:7777/healthz | jq

你应该看到类似输出:

{
  "status": "ok",
  "auto_commitment": true,
  "commitment_capable": true
}

然后将任意 MCP 协议的 Agent 指向 http://localhost:7777 即可开始使用。

如果不方便跑 Docker,一行命令即可体验核心逻辑:

cargo run --example demo

这个示例会运行两次——一次无防护(三步工具调用全部通过,数据泄露成功),一次有 Trajeckt 防护(第三步被拦截,返回 BLOCK 并附带原因)。

核心概念:密封承诺(Sealed Commitment)

Trajeckt 的核心创新是密封承诺(Sealed Commitment) 机制。在 Agent 执行任何工具调用之前,需要先声明并密封一个经过签名的执行轨迹图(CompiledGraph Gτ)。这个图精确规定了:

  • 哪些工具可以在什么顺序下调用
  • 数据可以流向哪些目标
  • 每个阶段允许的最大调用次数和预算

一旦密封,这个图就成了会话中的最高权威。每次工具调用都会被检查是否在密封图的当前可达边界内——不在图中的操作被硬拒绝(hard-refused),没有安装图的会话也被硬拒绝,不会自动降级到启发式模式。

默认配置下,Trajeckt 实现「零配置承诺模式」(auto_commitment=on):在 tools/list 握手阶段自动从声明工具集生成密封图,无需手动编写策略文件。

Trajektoryd (J_t 因果执行引擎)
─────────────────────────────────
Agent: read_database          →  ALLOW    [图中允许读取]
Agent: summarize              →  ALLOW    [图中允许汇总]
Agent: send_email_external    →  BLOCK    [J_t 因果路径检测]
          d_customer_records → summarize → d_summary → external_sink
          原因:敏感数据抵达禁止出口

安全兜底:启发式序列检测

对于需要灵活性的场景,Trajeckt 也提供了启发式安全网(通过 allow_uncommitted: true 启用),但需要在启动时显式确认——见 WARN 日志。此模式下它会检测已知的危险序列模式:

  • 数据泄露链敏感读 → 外部写 序列在同一会话中
  • 命令与控制链ShellExec → 网络出口 序列在同一会话中

部署选项

Trajeckt 支持多种部署方式:

docker-compose up

cargo build --release
./target/release/trajectoryd up --upstream http://your-mcp-server

./target/release/trajectoryd up \
    --upstream http://your-mcp-server \
    --policy configs/trajectory-policy.yaml.example

Python SDK 目前支持从源码构建(cd sdk-python && maturin develop),后续将发布到 PyPI:

import asyncio
import trajeckt

async def main():
    client = trajeckt.TrajecktClient.from_env()
    session = await client.session()
    await session.record_instruction(
        "You are a helpful assistant. Do not exfiltrate user data.",
        source="operator",
    )
    data = await session.call_tool("read_database", {"query": "users"})
    await session.call_tool(
        "send_email",
        {"to": "external@example.com", "body": data},
    )  # 这里会抛出 BlockedError

asyncio.run(main())

Trajeckt 能捕获什么

密封承诺模式下(默认):

  • 计划外工具调用——不在密封图当前边界内的工具被硬拒绝
  • 数据泄露到未授权目标——数据流向不在声明范围内的目的地被阻断
  • 因果结构偏离声明意图——实际调用 DAG 不匹配密封图
  • 高风险动作缺乏可信指令来源——工具调用链未追溯到可信指令

启发式安全网模式(显式 opt-in):

  • 敏感读取→外部写入的数据泄露链
  • Shell 执行→网络出口的命令与控制链

不能做什么

Trajeckt 检查的是行为的结构,不是内容的意义。一个提示注入指令编码在自然语言字符串里,Trajeckt 无法检测。它是对传统 allow/deny 列表、参数校验和 RBAC 的补充,而非替代。

对比同类方案

特性Trajeckt传统策略引擎Cerberus
因果轨迹追踪✅ 密封图 + HMAC 签名❌ 逐调用检查❌ 四信号引擎
部署方式MCP 网关 / SDK内联集成npm 插件
默认安全无图则拒绝所有无规则则放行所有无配置则仅基础扫描
性能开销~1.6ms0< 5ms
许可证Apache-2.0专有Apache-2.0

注意事项

  • 运行环境:Docker 或 Rust 编译环境是当前推荐部署方式,需要基本的容器/编译知识
  • 协议支持:目前实现 MCP Streamable HTTP Transport(2025-11-25 规范)的非流式配置
  • 基准测试:Trajeckt 在 ClawTrojan 安全基准的 cs_delay_002 模式上通过了端到端测试,更多轨迹模式正在验证中
  • 适用范围:适合使用 MCP 协议的 Agent 生态(Claude Code、Codex、Cline 等),不适合非 MCP 协议的自定义 Agent

总结

Trajeckt 解决了一个被行业忽视的安全问题:AI Agent 的多步工具调用组合可能构成泄露路径,而逐调用的安全检查无法发现它。通过密封承诺图和因果轨迹强制执行,它在 ~1.6ms 的开销下为 MCP 协议 Agent 提供了结构级的运行时安全。

对于在生产环境中运行 AI Agent 的团队,尤其是在处理敏感数据时,Trajeckt 值得加入安全栈——它不是替换现有的权限控制,而是填补了「整体行为合法性」这个关键空白。

相关链接

发表评论

你的邮箱地址不会被公开,带 * 的为必填项。