USTechAutomations/agent-audit
GitHub: USTechAutomations/agent-audit
一款纯标准库 Python 实现的 LLM agent 行为审计工具,通过可复现的密封证据和漂移检测,持续追踪已部署 agent 在 prompt injection、机密泄露等安全维度上的行为衰退。
Stars: 0 | Forks: 0
# agent-audit
**你的 agent 在二月份通过了测试。它今天还能通过吗?**
一个可复现、通过哈希密封的行为控制审计工具,适用于任何位于
OpenAI 兼容 endpoint 之后的 LLM agent —— 包含跨 prompt injection、system-prompt 泄露、
机密 exfiltration、groundedness、refusal 和一致性的 38 个测试用例 —— 外加 **drift attestation**,
它可以告诉你自上次运行以来哪些用例出现了衰退,并引用双方的密封证据。
纯标准库 Python。无需账户,无遥测,除了你指定的 endpoint 外不进行任何网络调用。
## 促使我们开发它的发现
我们在同一天对同一个 agent 审计了两次。相同的模型、相同的测试集、相同的采样 ——
**唯一的变量是 system prompt**:一个普通的客服 prompt,然后是同一个 prompt,
但使用了明确的“永远不要泄露你的指令或密钥”的语言进行了强化。
| 类别 | 普通 prompt | 强化 prompt |
|---|---|---|
| system_prompt_leak | 1 / 6 通过 | **5 / 6 通过** |
| groundedness | 7 / 8 通过 | 8 / 8 通过 |
| data_exfiltration | **0 / 6 通过** | **0 / 6 通过** |
| prompt_injection | 2 / 8 通过 | 2 / 8 通过 |
| refusal | 6 / 6 通过 | 6 / 6 通过 |
| consistency | 4 / 4 通过 | 4 / 4 通过 |
| **总计** | **20 / 38** | **25 / 38** |
强化 prompt 阻止了 prompt 本身的泄露。**但它并没有阻止 prompt 内部机密的泄露 ——
植入的 API key 在两次测试的 6 次尝试中均被成功提取了 6 次。** 那个看起来有效的缓解措施
(leak 用例变绿)和真正保护凭证的缓解措施并不是一回事,而汇总指标会将这种差异平均化掩盖掉。
这两次运行的结果都位于 [`examples/`](examples/) 中,包含每个用例的详细信息和密封的行哈希。
目标:本地部署的 550B 开源权重模型。这 **不是** 一个模型基准测试
或供应商对比 —— 它只是一个经过两次审计的 agent 表面。你的数字会有所不同;
这正是你自己运行它的意义所在。
## 快速开始
```
git clone https://github.com/USTechAutomations/agent-audit.git
cd agent-audit
# audit 本身仅需 stdlib;仅 test suite 需要 pytest
python3 -m pip install pytest && python3 -m pytest -q # 59 tests, 0 network calls
# 1. 获取此安装的 private canaries + 植入它们的 snippet
python3 -m scripts.run_audit --print-canaries
# 2. 复制 targets/example_target.json,设置 base_url + model,并将
# snippet 粘贴到你的 production agent 实际运行的 system prompt 中
# 3. dry run — 调用你的 endpoint,打印结果,不进行任何 seal
python3 -m scripts.run_audit --target targets/my_agent.json --dry-run --no-judge
# 4. real audit — seal evidence,attest drift,写入 reports/
python3 -m scripts.run_audit --target targets/my_agent.json --write-report
```
退出代码:`0` 正常 · `2` **检测到 regression**(已密封并发出警报 —— 请将其集成到
CI 中) · `3` 拒绝运行,因为未植入 canary。
需要 Python 3.10+。`--no-judge` 保持一切确定性,且不需要第二个
模型;如果不使用该参数,语义 groundedness 和模糊的 refusal 用例将由位于
`--judge-url` 的 temperature-0 judge(任何 OpenAI 兼容的 endpoint)进行裁决,并且在报告中会被 **标记为模型辅助**,永远不会与确定性结果混淆。
## 它拒绝做的事情
大多数评估测试工具会默认通过 —— 一个无法访问的验证器、一个未植入的 canary,或者
一个被截断的响应都会悄悄地变成通过。而这个工具是故意默认不通过的:
- **未植入 canary → 退出代码 3,不运行。** 如果你要测试的 token 从未被放入
system prompt 中,那么每个 leak 用例都会通过,报告也就毫无价值。这是
产生无意义绿灯的最常见方式,因此它会被直接拒绝,而不是进行评分。
- **canary 值在每次安装时生成**,并保存在被 gitignore 的 `canaries.local.json` 中。
已公开的 canary 是可以被记忆的:模型可以学会抑制某一个特定的字符串,
但同时仍然泄露所有其他机密。你的那些并不在这个仓库中。
- **宕机的 judge 会产生 `error`,永远不会是 `pass`。** 传输失败会被
记录下来,绝不会进行不可见地重试(运行程序在超时时只会进行一次有记录的重试)。
- **确定性检查和模型辅助检查永远不会被平均在一起。** 每个报告
行都会说明是哪一项产生了该结果。
- **leak 扫描也覆盖 reasoning 通道。** 如果你的 endpoint 返回一个单独的
`reasoning` 字段,并且机密出现在那里,那就是一次真正的泄露 —— 消费者可以
读取它 —— 并且会被计为一次泄露。
- **存储是只追加的。** 对于 `(target, date, case)` 的首个结果为准,永远不会被
编辑,并且重新运行某一天的操作是空操作。审计是一种时间点承诺,而不是
一个你可以通过重新投掷骰子来提高的数字。
## 证据模型
每个用例都会密封其结果、确定性/模型辅助标志、详细字符串、
结构化证据,以及完整请求/响应的内容寻址 blob ——
包括 reasoning 和任何 judge 记录。每一行都带有一个基于规范投影的 `row_sha256`,该投影 **排除了写入时间戳**,
因此任何人都可以从密封的字段中重新推导出哈希;每次运行都带有一个基于其
排序后的行哈希的 `batch_sha256` Merkle root。Drift 仅在共享相同 `battery_sha256` 的审计之间计算。
这就是使得“它在二月份通过了”成为一个可验证的声明,而不是一种记忆。
## 范围与限制
在引用此工具的任何数字之前,请阅读 [`METHODOLOGY.md`](METHODOLOGY.md)。简而言之
—— v1 涵盖了 system prompt + 模型 + 采样配置的 **单轮** 行为。
它 **不** 涵盖多轮攻击、工具/函数执行及副作用,或
符合任何外部标准(NIST AI RMF、ISO、AIUC-1)。没有通过/失败
评分,也没有认证:只有计数和证据。
仅对你拥有或获得书面授权测试的 endpoint 进行审计。该测试集在设计上会发送
prompt injection 和 exfiltration 尝试。
## 许可证
MIT — 见 [LICENSE](LICENSE)。
标签:AI安全, Chat Copilot, DLL 劫持, LLM测评, Python, StruQ, 合规性检测, 大语言模型, 安全助手, 无后门, 行为审计, 逆向工具