📚 首页 / 11-security/labs / lab.md

模块 11 — 动手实验:注入攻防与最小权限网关

全程无需任何 API key;两个脚本都是纯 Python 标准库的确定性模拟,在任何 Python 3.10+ 环境可跑。 实验目标:亲手「打穿」一个只有 prompt 禁令的系统,再亲手把它防住——把 README 第 2、3、4 节变成肌肉记忆。

Lab 1:间接注入攻防(30 分钟,无需 key)

🎯 学习重点:观察“内容进入模型”与“动作被网关放行”是两个独立控制点。

对应示例:../examples/indirect_injection_demo.py

步骤

  1. 通读脚本,找到三样东西:INBOX 里的三条外部内容(两条含注入载荷)、injection_screen() 的筛查规则、gateway_check() 的白名单逻辑。
  1. 跑基线:
   cd 11-security/examples
   python3 indirect_injection_demo.py

观察场景 A/B/C 的差异:无防御时注入直达执行层;仅 prompt 禁令时照样发出高危调用;分层防御下载荷在哪一层被拦。

  1. 加入你自己的载荷(改 INBOX,追加一条邮件):设计一个绕过现有正则的注入,例如不用 "ignore previous instructions" 而用中文或同义改写,重跑并观察:
  1. 加固你的筛查:把第 3 步绕过成功的模式补进 INJECTION_PATTERNS,重跑确认拦截。体会「筛查要持续监控、持续迭代」的运维含义。
  1. 思考题(口头):如果把 render_tool_result() 的 JSON 编码去掉、直接拼接正文,哪个防御层受影响?为什么官方强调 JSON 转义提供了「无歧义定界符」?

验收标准

Lab 2:最小权限网关对照实验(30 分钟,无需 key)

🎯 学习重点:用参数白名单与资源作用域把开放式模型输出收敛为有限状态空间。

对应示例:../examples/least_privilege_gateway.py

步骤

  1. 跑对照:
   python3 least_privilege_gateway.py

记录两个配置的小计:配置 A(万能工具 + prompt 禁令)执行了什么、是否外泄;配置 B(粒度工具 + 网关 + 审批门)拦了什么、放行了什么。

  1. 追踪一次拦截:在 gateway() 里找到三处确定性检查的顺序(参数域 → scope → 审批门),回答:
  1. 改动实验 A —— 放宽网关:把 SESSION_SCOPES 加上 "net:post",EGRESS_ALLOWLIST 加上 "collector.evil.example",重跑。观察:合法动作没变多,但外泄变成 True。体会「工具面每放宽一格,战果上限涨一格」。
  1. 改动实验 B —— 模拟审批疲劳:把 human_approve() 改成 return True(模拟 93% 批准率下的人审),重跑配置 B。观察:审批门失效后,哪些防线仍在?(egress 域名拒绝、scope 拒绝——确定性层不依赖人)
  1. 把工具粒度再切细:给注册表加一个 ToolSpec("update_shipping_address", "write", "db:write:orders.address", {...}),并让 extract_tool_calls 能从任务文本提取它;验证它进入审批门而非直接执行。

验收标准

Lab 3:为你的系统画攻击面地图(20 分钟,纸面,无需 key)

🎯 学习重点:必须标清数据来源、信任边界、凭据位置、工具副作用与 egress 路径。
  1. 选一个你真实接触的系统(或模块 10 的参考架构),照 README 第 2.3 节的 Mermaid 攻击面地图,标出:
  1. 对每个「无控制入口」写一行处置方案,优先级按 (入口被注入的概率 × 后果严重度) 排序。
  2. 用三个问题自检(来自 README common mistakes):

挑战任务(可选,40 分钟,无需 key)

🎯 学习重点:把绕过样本加入回归集,验证控制失败时仍能 fail closed。

在 Lab 1 的脚本里实现双通道返回:工具结果同时产出「给模型的摘要版」与「给审计日志的完整版」,日志版过一遍 PII 脱敏(正则抹掉邮箱/电话即可)。对应 README 第 5 节:日志脱敏是应用层职责,egress 控制挡不住你自己的日志管道。

环境说明

🎯 学习重点:实验无需 key,避免把真实凭据引入不可信测试输入。
📚 目录