安全团队希望在攻击者发现内存安全漏洞之前就能将其定位,但现有工具存在诸多困难:静态分析器误报率极高,导致审查者不再阅读其输出;模糊测试(fuzzer)则需要为每个入口点手工编写测试框架才能有所发现。本教程演示如何使用 Claude Agent SDK 构建一个漏洞发现代理,它借助 Claude Code 内置的 Read、Grep 和 Glob 工具读取源代码,分析哪些输入可能导致内存损坏,并生成可供审查者直接采用的研究结论。
学完本教程后,你将能够:
- 通过一个多轮 ClaudeSDKClient 会话运行“先引导、后访谈”的威胁建模流程,并生成 THREAT_MODEL.md 文件
- 使用内置的 Read/Grep/Glob 工具驱动自动化查找循环,无需自己编写文件访问代码
- 将查找、分类和报告串联为独立的 query() 调用,输出符合预定义模式的 JSON

前置条件
所需知识:
- Python 基础知识,包括 async/await
- 足够的 C 语言能力,能读懂一个 45 行的文件并能识别 memcpy
所需工具:
- Python 3.11+
- Node.js 18+ 及 Claude Code CLI:npm install -g @anthropic-ai/claude-code
- Anthropic API 密钥
针对任何真实目标的要求: 获得评估该代码的授权。本教程附带一个极小的自包含文件 canary.c,其中植入了多个漏洞,以便你在不接触生产代码的情况下完整运行整个流程。
步骤 1:设置环境与行动背景
我们定义一个 ENGAGEMENT_CONTEXT 块,并将其作为 system_prompt 传递给每个代理。它记录了本次评估的范围(代码所有者授权、隔离只读沙箱、发现结果将负责任地披露),使得流程中的每一步都遵循相同的、已记录的基本规则。请确保对任何真实目标都满足这三项声明。
关于网络安全防护的说明: Claude 在 API 层应用了实时网络安全防护。如果你的工作涉及真实代码库并触发了这些防护措施,请通过该页面申请网络安全验证计划(Cyber Verification Program,CVP):这是一个免费的、基于申请的计划,能让专业人士以最小干扰继续合法的双重用途安全工作。
步骤 2:加载测试目标
vulnerability_detection_agent/canary/canary.c 是一个约 45 行的 C 程序,故意植入了三个内存安全漏洞(堆缓冲区溢出、栈缓冲区溢出和释放后使用),每个漏洞可通过输入文件开头的不同“魔法字节”触发。这些漏洞未做标记;步骤 4 中的查找代理必须像处理真实代码一样,通过阅读逻辑来定位它们。当你准备好测试自己的代码时,请将 TARGET_DIR 指向你的代码仓库。
步骤 3:对目标进行威胁建模(先引导,后访谈)
威胁建模独立于任何特定漏洞来回答“这个系统可能出什么问题、谁会这么做、哪些结果值得关注?”。一个威胁(“攻击者通过不受信任的文件解析实现内存损坏”)在补丁修复后依然存在;而一个漏洞(“第 31 行未对 len 进行边界检查”)则会被修复。查找循环负责搜索漏洞;威胁模型则告诉它去哪里搜索,并告诉分类阶段如何评分。
我们通过一个 ClaudeSDKClient 会话的两轮互动来构建威胁模型:
- 引导: Claude 使用内置的 Read 工具读取代码,并草拟模型(上下文、资产、入口点和信任边界、威胁,以及代码无法回答的待解问题)。
- 访谈: 应用程序所有者回答待解问题,Claude 调整可能性和影响,然后在目标文件旁写入 THREAT_MODEL.md。
将两轮放在同一个客户端会话中,意味着访谈轮可以查看引导轮的工具调用结果,而无需重新发送源代码。对于一个 45 行的测试程序,两轮内容都很精简;但关键在于输出结构:入口点表格(你将据此对真实代码仓库进行并行查找代理分区)和待解问题列表(引导到访谈的交接点)。
步骤 4:运行自动化查找循环
如果使用原始消息 API,这一步将是一个手工编写的 while stop_reason == “tool_use” 循环,并配备自定义文件工具。Agent SDK 处理了所有这些:我们只需调用一次 query(),并设置 allowed_tools=[“Read”, “Grep”, “Glob”] 和 disallowed_tools=[“Bash”],Claude Code 便会自主运行探索-读取-推理循环。cwd=str(TARGET_DIR) 将代理指向测试程序,system_prompt={“type”: “preset”, “preset”: “claude_code”, “append”: …} 保留了 Claude Code 的默认系统提示(已告知代理其工作目录),同时附加了我们的行动背景,因此代理永远无需猜测自己的位置。通过禁止 Bash/Write/Edit,代理保持只读状态。
提示中最关键的部分仍然是质量等级评估标准。 若没有它,LLM 漏洞狩猎者会报告每一个能发现的空指针解引用和失败的断言,这些虽然是真正的崩溃,但几乎无法利用。该标准告诉代理哪些崩溃类别值得提交(堆/栈溢出、释放后使用、受控地址写入),哪些只是需要继续阅读的路标。这一个区块在很大程度上决定了安全工程师会采纳的报告与会被忽略的报告之间的差别。
生产版本会将 “Bash” 加入 allowed_tools,以便代理可以用 -fsanitize=address 编译并确认每个崩溃;但这应放在锁定的容器内进行,因此本教程保持只读状态。
步骤 5:筛选原始发现结果
查找代理已调优为高召回率,因此其输出通常包含重复项(一个根因从两条路径触发),偶尔也会包含一个站不住脚的发现。分类阶段就是过滤器:一个新的 query() 会话重新读取代码,验证每个发现是否与实际代码行对应,合并重复项(按根因),并重新推导严重性(基于威胁模型中信任边界内的可达性)。我们有意识不让分类阶段继承查找代理的严重性评分;独立重新推导是一种廉价的方式来发现过度自信。
步骤 6:输出结构化报告
下游系统(问题跟踪器、仪表板、SIEM)需要结构化数据。最终一次无工具的 query() 将分类后的发现转换为符合明确模式(schema)的 JSON。我们将每个字段标记为必填,并使用 null 表示“不适用”,以便模型无需猜测可选性;在生产环境中,你将使用 jsonschema 进行验证,并在失败时重试。
总结与下一步
你已经使用 Agent SDK 构建了完整的威胁建模、查找、分类、报告流水线:一个多轮 ClaudeSDKClient 会话用于威胁建模,以及三个一次性的 query() 调用用于其余步骤,借助 Claude Code 内置的文件工具进行探索。
需要牢记的关键模式:
- 使用 ClaudeSDKClient 进行对话,使用 query() 进行一次性任务。 威胁建模访谈需要引导轮作为上下文;查找、分类和报告不依赖彼此的工具调用记录,因此无状态调用更简单。
- cwd + allowed_tools 替代了手工编写的工具。 作用域限定在目标目录的 Read/Grep/Glob 就是整个查找代理的脚手架。
- 分类是单独的一轮。 独立于查找代理重新验证和评分,能够廉价地捕捉过度自信。
进一步探索:
- 使用托管版本。Claude Code Security 以托管产品的形式提供相同的查找和分类能力,你只需指向一个代码仓库,Anthropic 负责处理沙箱化和扩展。
- 扩展到真实代码仓库。 将 cwd 指向真实的代码仓库,在沙箱容器内将 “Bash” 加入 allowed_tools,以便代理能用 -fsanitize=address 编译并确认崩溃,然后使用 asyncio.gather 为威胁模型中的每个入口点生成一个 query()。
- 将报告接入你的跟踪系统。 使用 jsonschema 验证步骤 6 的 JSON,将其映射到 SARIF 或你的工单模式,然后 POST 提交。
原文:https://platform.claude.com/cookbook/claude-agent-sdk-06-the-vulnerability-detection-agent
文章来自:51CTO
