项目:离线 Agent 威胁评审

你要完成什么

对一个“读取一封邮件并生成草稿,绝不自动发送”的 Agent 建立严格场景契约,并用确定性 Python 规则找出从不可信邮件到工具、身份、数据出站、供应链和运营控制的风险。项目离线运行,不调用模型、连接器或网络,不需要密钥。

这不是漏洞扫描器或渗透测试。它训练的是一条可复用工程链:

用途/非目标 → 资产与边界 → 能力/身份/依赖 → 控制契约
           → 确定性发现 → PASS/REVIEW/BLOCK → 回归测试

文件说明

文件用途
examples/threat_review.py严格 JSON 解析、契约校验、11 条教学规则、决策与 CLI
examples/agent_scenario_vulnerable.json故意暴露过多能力的场景,预期 BLOCK
examples/agent_scenario_hardened.json最小权限只读场景,预期 PASS
examples/agent_scenario_contract_error.json含未知字段,预期契约错误
examples/test_threat_review.py合同、规则、指纹、CLI 与自测的回归测试

输入显式声明资产分类、信任边界、非权威来源、身份 scope/有效期、工具执行身份/副作用/具体 endpoint 与资源、数据出站、依赖摘要、审批/沙箱/记忆流和风险政策。严格契约拒绝重复 JSON key、NaN、未知字段、悬空引用、矛盾的 mode/effect、宽泛目的地和未覆盖严重度,避免“脏输入被静默解释”。

运行环境

  • Windows 11 + PowerShell 7;
  • 当前稳定 Python 3;
  • 只使用标准库,不安装依赖。

从本笔记所在目录运行:

Set-Location '.\examples' # 进入场景、实现和测试所在目录,以下相对路径才可直接运行。
 
# 漏洞场景:退出码 1,action=BLOCK
python -B .\threat_review.py --scenario .\agent_scenario_vulnerable.json # 运行故意宽权限的场景,验证其稳定得到 BLOCK。
 
# 加固场景:退出码 0,action=PASS
python -B .\threat_review.py --scenario .\agent_scenario_hardened.json # 运行最小权限的加固场景,验证其得到 PASS。
 
# 输入契约错误:退出码 2
python -B .\threat_review.py --scenario .\agent_scenario_contract_error.json # 用未知字段 fixture 验证输入契约 fail-closed。
 
# 内置冒烟检查
python -B .\threat_review.py --self-test # 执行脚本内置的快速自检路径。
 
# 80 项测试;再用 -O 和 warnings-as-errors 验证测试不依赖 assert/警告
python -B -m unittest discover -s . -p 'test_*.py' -v # 正常模式下发现并详细运行全部测试。
python -B -O -m unittest discover -s . -p 'test_*.py' # 用 -O 验证生产规则不依赖 bare assert。
python -B -W error -m unittest discover -s . -p 'test_*.py' # 将 warning 变成失败,检查更严格的运行条件。

PowerShell 中退出码在 $LASTEXITCODE。这里 BLOCK/REVIEW 返回 1 是预期业务决策,不等于程序崩溃。

阅读实现

1. 严格契约

load_json 拒绝重复 key 和非标准常量;validate_scenario 对每层做精确字段、类型、枚举、唯一 ID 与引用完整性检查,并返回深拷贝。契约错误统一退出 2。

2. 11 条教学发现

规则覆盖间接注入到副作用工具、非必要功能、共享/长期/过宽身份、弱审批、目的地缺少约束、敏感数据无出站验证、依赖未固定/未验证、沙箱不足、工具参数未验证、记忆投毒以及审计/限流/紧急停用缺失。

每条发现都含资产、攻击路径、影响、建议控制、负责人和验证方法。结果按严重度与 ID 稳定排序,便于 diff 和门禁。

这 11 条规则不是 OWASP Agentic Top 10 的自动合规映射。它们没有完整验证 Agent 间消息身份/完整性、跨 Agent 级联、人的信任校准或自主偏离/rogue 行为;多 Agent 项目应把这些风险另建场景、终态断言与演练,而不是用本项目的 PASS 代替。可将协作侧的负向合同接到 身份、授权与跨边界信任,再把两类结果共同放入发布门。

3. 决策与证据指纹

场景内冻结哪些严重度 BLOCK、哪些需要 REVIEW;无触发项才 PASS。报告用场景与发现的规范 JSON 计算 SHA-256 指纹,帮助确认比较的是同一证据,但指纹不是数字签名,也不能证明输入真实。

验收任务

基础验收

  • 漏洞场景产生 AS-001 到 AS-011,动作为 BLOCK。
  • 加固场景无发现,动作为 PASS。
  • 契约错误场景返回退出码 2,不产生看似有效报告。
  • 三种测试模式全部通过且不生成缓存。

理解验收

逐条解释为什么漏洞场景触发 11 项规则,并把每项映射到本库相应课程。特别说明:为什么删除 send_mail 比提示模型“不要发送”更强;为什么工具 schema 仍需授权;为什么 PASS 不能声称系统已安全。

扩展任务

复制加固场景,构造一个只把依赖 pinned 改为 false 的场景,确认得到 REVIEW 和 AS-007。再设计自己的“共享盘转工单”JSON;先写预期发现和决策,再运行。若要新增字段,先改契约和失败测试,不要让未知字段静默通过。

自测题

  1. 为什么外部内容、模型输出和工具返回都应视为不可信?
  2. required_for_purpose 如何帮助发现功能过多?它为什么不能代替人工威胁建模?
  3. 同一个身份同时有 mail.read 与 mail.send 的爆炸半径是什么?
  4. 为什么批准要绑定规范化参数与状态版本?
  5. 报告指纹能证明什么,不能证明什么?
  6. 规则全部未触发时,还缺哪些真实验证?

参考答案要点:确定性规则只能检查声明的有限契约;没有执行真实模型、身份提供方、工具、沙箱或网络,也没有验证 JSON 声明是否符合部署。因此 PASS 只表示“该输入未触发教学规则”。

进一步学习

参考资料