返回
官网 Claude 官方博客 AI 逐段翻译 发布 2026-05-27 08:00 收录于 08-11

用LLM保护源代码:Claude安全实践指南

DataHot 速览

Anthropic分享了使用Claude Opus进行源代码安全扫描的实践指南,强调发现漏洞已可并行化,瓶颈转向验证、分类和修补。截至2026年5月22日,已披露1596个漏洞,仅97个被修补。文章详细介绍了威胁建模、沙箱、发现、验证、分类和修补六个步骤,并提供了配套代码库和技能。

为什么值得关注:该指南展示了如何将LLM应用于代码安全这一数据场景,提供了可操作的流程和方法,对数据团队构建AI代理有借鉴意义。

本文目录 10 节
  1. 发现与修复循环
  2. 1. 威胁模型:定义什么算作漏洞
  3. 2. 沙盒:安全运行代理并验证可利用性
  4. 3. 发现:提供丰富上下文、更短的提示和有用的工具
  5. 4. 验证:过滤不可利用的发现
  6. 5. 分类:按根本原因去重,按前置条件和影响排序
  7. 6. 修补:闭环并改进下一周期的上下文
  8. 入门
  9. 展望未来
  10. 致谢

译文

AI 逐段翻译

模型能力正在快速且不均匀地发展。我们一直在与安全团队合作,以发现并修复他们自己的代码和开源软件中的漏洞,这项工作让我们更好地理解了如何利用模型来保护源代码。我们的主要结论是:发现漏洞现在可以轻松并行化,而瓶颈已经转移到验证、分类和修补上。

为了说明这种差异,作为我们自己的扫描工作的一部分,截至2026年5月22日,我们已披露了1596个漏洞。据我们所知,其中97个已得到修补。

本指南将介绍如何使用Claude Opus构建威胁模型、发现代码库中的漏洞,然后进行验证、分类和修补。虽然我们并非拥有所有答案,但我们将分享团队如何扩展发现范围,以及在后阶段哪些措施有所帮助。立即开始使用随附的仓库,其中包含用于交互式工作流的技能和用于自主扫描的演示工具;我们会在阅读时指出实现每个步骤的技能。

发现与修复循环

发现并修复最多漏洞的团队汇聚于现有最佳实践的变体。我们将其提炼为六个步骤的顺序:

  1. 威胁模型: 在开始扫描之前,确定什么算作漏洞。
  2. 沙盒: 构建一个沙盒环境,以隔离代理并证明漏洞利用。
  3. 发现: 让模型在你的源代码中寻找漏洞。
  4. 验证: 独立确认哪些发现实际上可利用。
  5. 分类: 对发现进行去重、分配严重性,并确定哪些需要优先修复。
  6. 修补: 应用修复,确认漏洞被消除,并寻找变体。

前两步——构建威胁模型和沙盒——是为循环其余部分做的准备。这些通常针对每个代码库完成一次,并在底层系统发生变化时重新审视。接下来的四个步骤是你对源代码运行的循环:发现、验证、分类和修补。

在代码库上的首次运行通常会得到最多的发现。后续运行的发现往往较少——但通常更复杂——因为较简单的漏洞已在之前的运行中修复。然而,不要期望第n次运行有零个新发现。模型是随机的,大的代码库可能存在长尾漏洞,即使代码不变,这些漏洞也会持续出现。

在首次迭代代码库时,你应该多次运行该循环,根据净新增发现的数量和你对该系统的风险承受能力来决定何时停止。首次迭代之后,继续(1)定期扫描,或(2)每当代码有重大变化时扫描。

接下来,我们将详细讲解每个步骤,解释其重要性、产出什么以及如何实施。

1. 威胁模型:定义什么算作漏洞

误报最常见的原因是模型对信任边界缺乏良好理解。模型可能会将代码标记为易受攻击,因为它假设客户端可能发送损坏的值,或攻击者可以控制配置,尽管这些输入在你的环境中是受信任的。反之,模型可能假设面向互联网的服务仅限内部使用,从而少报真实漏洞。在这两种情况下,模型出错的是威胁模型,而不是代码。

一个团队注意到他们的发现中有一个模式:模型在具有文档化良好的威胁模型、系统设计文档、需求和约束的系统上表现最好。当威胁模型定义明确时,模型的发现“在90%的情况下是可利用的。”

你可以通过两个步骤与Claude一起构建威胁模型:

首先,从代码、文档和漏洞历史中进行引导。 将你在第一天会交给新安全工程师的东西输入给模型:架构文档、维基、入口点、git历史和过去的漏洞。这有助于克服仅从代码推断隐性知识、权衡和设计决策的挑战。然后,让模型创建包括系统上下文、资产、入口点和信任边界的威胁模型。最后,让模型将过去的错误聚类,并列出现相关的漏洞类。确保威胁模型记录了你不关心哪些漏洞以及为什么。

一个团队审查了数百个过去的CVE和安全修复提交,将它们提炼为“错误形状”提示,并向模型问了两个问题:修复是否完整,它是否应用到所有其他地方?他们在一小时内发现了三个可利用的问题。正如他们所说:“‘过去人们利用了什么’有时比‘在这个代码库中找我漏洞’更容易取得成功的捷径。”

其次,让模型采访一个非常了解该系统的人。考虑Shostack的四个问题:我们正在建造什么?可能出什么问题?我们正在采取什么措施?我们做得好吗? 先运行引导步骤,这样受访者不必从头开始。这样,他们可以从草稿开始,而不是花几个小时研究并从零构建威胁模型。虽然采访步骤是可选的,但它提供了模型无法从代码或文档中获得的上下文,这改善了威胁模型。

一些做法可以产生巨大影响:

  • 考虑依赖方的安全政策。 许多开源项目都发布了这样的政策。例如,vLLM的security.md、SQLite的“防御黑暗艺术”,以及ImageMagick的安全策略。你的威胁模型应该直接考虑它们,而不是从头重建一个策略。
  • 明确指出什么是受信任的。如果你信任配置文件或经过身份验证的客户端,请在威胁模型中记录这一点。这些假设有助于区分不可利用的缺陷和实际可利用的漏洞。
  • 在代码中包含一个THREAT_MODEL.md文件。将其放在仓库中,并随着代码变更而更新。发现代理可以在搜索之前读取它,跳过已知的非问题。

你会在两个地方使用威胁模型。在发现阶段,作为范围界定:对代码进行分区,优先处理目标,并跳过不在范围内的部分。这有助于处理无法完全扫描的大型代码库。在分类阶段,作为过滤器:在广泛扫描后,使用威胁模型更好地根据你的系统和环境调整严重性。

一个团队扫描大型项目时,误报率为40%,他们深入调查了原因。发现结果可复现,并且PoC证实了可利用性。但拥有代码的开发团队将其视为误报,因为这些缺陷不符合项目的威胁模型。另一个团队的CISO简洁地说:“[模型]对代码有很好的背景,但对我们的情况没有很好的了解。”

尝试威胁模型技能。它遍历本节描述的两个步骤——引导从你的代码、CVE和git历史中生成草稿,访谈则引导系统所有者通过Shostack的四个问题来完善它。输出是一个THREAT_MODEL.md文件,用于发现和分类步骤。

2. 沙盒:安全运行代理并验证可利用性

沙盒的一个目的是保护你的系统。为了使模型能够安全自主地运行,你需要一个强大的隔离层。没有它,代理可能会超出目标范围并做出意外的事情。

一个团队告诉模型它没有网络访问权限——实际上它有——模型发现它仍然可以从GitHub获取。另一个团队观察到代理在扫描过程中回答了GitHub问题。这两个行为都不是恶意的,但都表明需要通过代码和配置来强制执行约束。

将隔离与你的威胁模型相匹配。对于读取代码的发现代理来说,容器是可以的,但要在microVM(如Firecracker)或完整VM中运行目标和其PoC,并锁定出站流量,以便无法访问你的生产系统。并且永远不要让代理获得凭据(~/.aws、~/.ssh、.env)。

仅在设置沙盒时给予网络访问权限。拉取依赖项,构建,安装工具,部署目标,并运行现有测试以确认一切正常。然后,快照环境并移除其网络访问权限。在扫描期间,仅允许通过本地代理路由到模型API的流量。在每次运行开始时加载快照,以便每次扫描都从相同的干净状态开始。

沙盒的另一个目的是证明可利用性。在静态扫描期间,模型读取代码并推测可能破坏的地方,但它无法测试路径是否可达或是否存在补偿控制。因此,模型可能会标记你实际上并不关心的不可利用的代码正确性缺陷。当团队构建了代理可以编译代码、运行测试并引爆概念验证的沙盒时,不可利用的发现显著减少。

一个攻击性安全团队构建了一个工具,为代理提供测试环境,并有一个简单的验证规则:只有当代理能够构建概念验证并在测试环境上运行它时,才算真正的阳性。他们六周后的评估是,“最大的效能杠杆是给模型测试环境、实时系统和运行PoC。”

在构建沙盒时,尽可能固定所有内容,以便每次运行使用相同的环境和代码:镜像标签、提交SHA、依赖项和构建命令。缓存本地副本,以便构建不需要网络,并力求容器持久,以便多个测试循环可以加载它。

一个团队的扫描标记了一个漏洞,后来发现是代理下载了旧版本的库而不是实际部署的版本。这被一位阅读转录并发现正在下载不同依赖项的工程师发现。他们现在构建Docker容器时固定依赖项以匹配生产环境,因此发现代理和验证代理操作的是攻击者会遇到的相同工件。

构建忠实于生产的沙盒很重要。排除依赖项(如队列或数据存储)可能导致漏报生产环境中可能存在的缺陷。相反,忽略生产防御(如WAF或身份验证网关)会导致模型报告生产环境已缓解的不可利用发现。

然而,如果由于云依赖、数据存储或其他现实世界的复杂性而无法构建具有代表性的沙盒,那么先进行发现步骤(如下)。你不一定需要在沙盒中运行PoC。前沿模型擅长仅通过分析源代码来发现漏洞。包括我们自己在内的几个团队都发现这很有效。权衡在验证阶段,没有运行中的目标,我们无法用PoC证明发现,所以需要更多时间进行验证。你也可以在发现结果数量证明合理后再投资构建沙盒。

参考工具README.md 以获取参考沙盒。在此实现中,代理和目标运行在gVisor隔离的容器中,出站流量锁定到模型API。目标从固定到特定提交的Dockerfile构建,setup_sandbox.sh处理设置阶段。

3. 发现:提供丰富上下文、更短的提示和有用的工具

给发现代理访问它可以根据需要加载的上下文,如威胁模型、架构文档和过去扫描的结果。当代理了解你的信任边界和系统实际部署方式时,它可以更好地识别针对你系统的特定漏洞。

我们发现前沿模型在发现阶段受益于越来越简单的提示。与直觉相反,更详细的提示会使发现效果变差——冗长的检查清单往往会降低模型的创造力,并产生更少的新颖漏洞。以下是一些在发现阶段有帮助的提示技巧:

  • 提供目标和上下文。 指出“为什么”和“什么”——为什么扫描,有意义的发现是什么样子,扫描什么系统——把“如何扫描漏洞”留给模型。前沿模型在安全任务上越来越擅长,过于详细的指示可能会限制它们的尝试范围。
  • 尝试要求特定漏洞类别。 如果你想根据先前的CVE或代码库语言专注于特定类型的漏洞,请说明。描述漏洞类别、它的作用以及它通常存在的位置,以便模型能在你的代码库中识别它。
  • 定义输出。 要求一个带有预定义字段的结构化报告,并将它们排序,使模型的推理能在每个字段的基础上建立。示例字段包括理由、发现、影响、严重性等。包括一个逃生舱,以便模型可以在弱发现时提前退出。

给模型提供搜索和阅读代码库的工具,如grep、glob等。也让模型使用你的团队可能使用的安全特定工具,如SAST扫描器或模糊测试器。询问模型特定任务需要哪些工具,并使其可用。最后,让模型按需构建工具:最近的前沿模型在编写所需工具方面越来越擅长。

除了源代码,一个渗透测试团队给了发现代理发送请求、检查响应和查询流量日志的工具。结果,代理不需要猜测路径是否可达,并且可以在运行时针对正在运行的应用程序测试每个候选者,将其真正率提高到接近100%。

让模型对系统进行第一遍扫描,以划分搜索空间,例如按攻击面、端点或组件。然后,将这些分区提供给并行的发现代理,以便它们不会收敛到相同的浅层漏洞上。最后,运行系统级遍,将分区级别的发现作为上下文来搜索漏洞。

尝试暴力破解发现的团队很快就遇到了收益递减。来自一个团队:“我们最初试图横向扩展并发送更多代理,但看到回报有限。”另一个团队增加了重点是数量和并行代理,得到了“大量问题”,其中大多数是彼此的重复项。

如果你有沙盒来运行目标,请要求发现代理构建发现的PoC,如脚本、崩溃输入或失败测试。构建PoC有助于代理迭代并确定发现,并且工件给验证代理提供了具体的证据来评估。尽管如此,代理无法重现的发现仍可报告,标记为未证实,以保持高召回率。

该vuln-scan 技能在此阶段很有帮助。它读取你的 THREAT_MODEL.md,将目标划分为重点关注区域,并针对每个区域扇出并行审查代理。输出是下一步直接使用的结构化发现。

4. 验证:过滤不可利用的发现

发现优化召回率;验证优化精度。换句话说,发现应尽可能多地找到漏洞——甚至不太可能出现的——而验证应排除实际上不可利用的发现。当代理试图在同一步骤中做这两件事时,它可能会自我审查并排除可利用的真正例。我们艰难地学到了这一点,要求发现代理同时验证会导致它们过滤掉真正的例,而单独的验证步骤本可以确认这些真正的例。

验证代理应与发现代理独立。在一个没有共享文件系统或对话历史的新容器中运行验证器。如果验证器接触到发现代理的推理,它可能只是同意而不是测试声明。因此,只给验证器(1)概念证明或书面发现,以及(2)代码库,以便它可以搜索发现者忽略的缓解措施(例如,上游验证、认证门、类型约束或不可达代码)。

如果一次验证遍仍然让太多不可利用的发现通过,尝试运行多个独立的验证器。它们可以考虑不同的角度或使用不同的模型运行。然后,采取多数投票。还要考虑有一个单独的法官在发现和验证代理的结果之间做出决定。

提示验证代理反驳发现代理的发现。让验证器假设每个发现都是误报,并搜索发现错误的原因。包括清晰的准则,验证代理可以用这些准则来确定发现是否为真正的正例。当发现代理的输出不包含PoC时,这最重要。目标是尽可能排除不可利用的发现,以减少人工审查的工作量。

在我们合作的团队中,添加对抗性验证器大约将使发现阶段的不可利用发现率减半。要求验证器同时构建确认利用的概念证明,将误报率降至接近零。总的来说,这两个步骤有助于显著减少下游的分类和修补负载。

如果你能在沙盒中充分重现生产环境(见步骤2),提示验证代理构建并执行可重现的概念证明(PoC)。如果PoC有效,你可以得出结论认为该发现是可利用的。注意,反过来不成立——未能生成有效的PoC并不能证明是误报。

一个扫描开源软件包的团队构建了一个验证步骤来闭环:扫描软件包,生成概念验证,然后部署一个使用该软件包并触发 PoC 的模拟应用。他们的观点是:“验证是最大的阻碍,PoC 就是验证。”

5. 分类:按根本原因去重,按前置条件和影响排序

验证确认发现是可利用的,而分类评估修补优先级。以前,当发现需要更多努力时,发现 bug 的工程师也会进行分类。现在,模型能在午饭前找到一百个候选,分类已成为瓶颈。

适当的分类有助于防止警报疲劳。如果你提交太多重复或严重性夸大的 bug,产品工程师可能不再阅读它们,即使是那些需要立即修补的。开源维护者尤其可能被未分类的发现淹没,因为他们收到来自许多依赖其软件的不同用户的报告。

多个团队分享了相同的经验:如果我们把一大堆发现交给产品工程师,其中大多数不可利用,他们会失去对报告的信心并放弃。他们还优先处理严重和高危的发现,以避免让下游工程师不堪重负。其他团队通过将模型指向他们现有的积压工作——先前扫描器、先前模型、漏洞赏金提交的未处理发现——并在几天内清理了数百个过时条目,取得了成功。

要对发现去重,考虑根本原因。扫描器通常会在多个调用点标记一个 bug,或报告单个根本原因的多个症状。这里有一个实用的方法:首先,使用廉价的确定性传递:同一文件、同一类别、漏洞行号在彼此十行之内。然后,让模型对剩余部分应用定性规则:

  • 视为重复:同一根本原因措辞不同;同一漏洞在多个调用点报告;缺少全局保护(如认证检查)按端点报告;或原因及其后果在同一路径中标出。
  • 视为不同:同一文件中的不同漏洞类别;不同变量到达不同汇点;一个辅助函数内的两个独立 bug;同一缺失检查在两个端点上,但每个都需要单独修复。

如果你的测试工具为每个发现生成 PoC 和补丁,另一种去重方法是检查一个发现的补丁是否也能解除其他发现的 PoC。

去重后,根据以下因素评估每个发现的严重性:

  • 可达性。攻击者能从真实入口点到达此代码,还是只能从内部代码和端点到达?
  • 攻击者控制。不受信任的输入是否完整到达汇点,还是上游有净化或约束?
  • 前置条件。触发 bug 需要什么条件:非默认设置、特定功能标志、攻击者必须命中的狭窄时间窗口?
  • 认证。未认证的攻击者能触发它,还是需要登录用户或管理员?
  • 读与写。攻击者只能读取数据,还是也能修改?
  • 爆炸半径。如果 PoC 触发,谁受影响?一个用户还是所有用户,一个租户还是平台,用户态还是内核?

为了将规则转化为分数,让模型在分配严重性之前写出对每个问题的回答。先检查证据可防止模型锚定于漏洞类别(“SQL 注入,所以严重”)然后夸大严重性。作为起点:无前置条件且未认证远程访问为严重或高危。一个或两个前置条件,或经过认证的路径,为中危。三个或更多,或仅本地,为低危。根据你的系统调整阈值。

模型可能因上下文不足而夸大严重性。它们可能不知道攻击者实际控制哪些输入,或者看不到补偿性控制。前者例如,SQL 注入如果由未认证请求触发则是严重,但如果由仅管理员配置文件触发则不是问题。后者例如,上游 WAF 或认证可能阻止利用,这从源代码本身可能看不出来。

解决方案是在分类期间提供威胁模型,告诉模型在你的系统中哪些类型的漏洞你关心哪些不关心。例如,说明“我们信任已认证客户端”可以简化或消除整个严重类别。

一个团队发现,除非基于某事验证或有更多关于某物是否符合威胁模型的上下文,否则模型常常过度自信。他们的修复是给分类代理与发现代理相同的威胁模型。

试试分类技能。它同时进行验证和分类:对每个发现进行多票验证,跨运行去重,并按推导出的可利用性重新排序。输出是一个简短、排序、拥有的列表,而不是原始倾倒。

6. 修补:闭环并改进下一周期的上下文

修补是闭环和修复漏洞的地方。它也有助于基于已验证的发现改进威胁模型——更新信任边界或需要更多审查的组件——并将过去的发现输入到下一次扫描的上下文中。每个周期都强化代码库,并使下一次扫描信息更充分。

修补前,编写一个在现有代码上失败的新测试。然后,实现修复并确认同一测试现在通过而不破坏其他任何东西。(是的,这是测试驱动开发)。如果不添加测试,修复可能悄然回归,而且很难追溯地证明 bug 是真实的。

一位渗透测试员发现,他们生成的补丁不一致——有些好,有些坏——直到测试工具告诉模型通过针对修补后的代码重新运行概念验证来验证补丁。通过给模型反馈以迭代,补丁质量大幅提升,节省了人工审查时间。

模型可能只狭隘地处理特定调用点的发现,而没有解决根本原因。简单地提示模型识别并修复根本原因可能是有效的。然后,让模型在两个层面寻找变体:(1)相同模式,即其他地方存在相同错误代码的其他调用点或副本;(2)相同类别,即一个存在SQL注入漏洞的代码库往往有更多SQL注入漏洞。用经过验证的发现和补丁更新威胁模型,以形成闭环。

在发布补丁之前,进行对抗性检查。让一个新的发现代理以攻击者的身份探测补丁,以确认补丁是全面的。然后,简化生成的补丁,以解决过于侵入性的补丁。最小化的补丁更容易审查,也不太可能引入新的错误。提示进行修复根本原因的最小更改——不要重构,不要顺手清理,不要重新格式化。

一个团队在他们最常见的补丁失败中说:“推荐的补丁往往尽可能具有限制性,以至于会破坏与其他服务的连接。它可以解决问题,但会破坏使服务首先能够工作的依赖关系。”

您可以针对一系列检查来验证每个补丁,从最便宜的检查开始:

  1. 构建。 补丁可以编译,并且新测试通过。
  2. 尝试复现。 原始PoC应该不再起作用。这可以捕获无效的补丁。
  3. 检查回归。 原始测试套件仍然通过。这可以捕获损坏或过度限制的补丁。
  4. 重新攻击。 一个新的发现代理进行对抗性检查。这可以捕获不完整的补丁。

最后,虽然模型可以编写补丁,但人类仍然需要负责。生成的补丁可能会以可预测的方式失败——修复症状而不是根本原因,阻止合法输入,或移除对依赖服务的访问权限。目标是尽可能多地验证每个补丁,使人工审查需要更少的精力。目标是通过对补丁的最小审查和更新,帮助开发团队专注于模型可能不知道的细微差别(例如,即将到来的更改、代码风格)。

试试 patch 技能。 它使用分流输出并为每个发现生成候选差异,并由独立的审查代理检查每个差异。

入门

尝试自己运行这个循环。克隆 defending-code-reference-harness 并在 Claude Code 中 运行 /quickstart。它会引导您在演示目标上完成从威胁建模到扫描再到分流的交互式工作流程。该仓库还包含一个自主运行框架和一个 /customize 技能,用于为您的环境更新该框架。

然后,在您自己的代码上运行它。选择一个服务或包。从代码和文档中启动威胁模型,并进行访谈。投资构建您环境的沙箱。扫描。用独立的代理验证发现。根据您的标准进行分流,并审查所有评级为高及以上的内容。修补。然后定期重新扫描。

您的第一次扫描将浮现出比您预期的更多的发现。大多数需要验证和分流。在预算更多扫描之前,先为扫描 之后 的流程做好预算。

您可能会发现以下一些资源很有帮助:

展望未来

我们相信,模型在代码中 发现和利用漏洞 变得越来越容易。因此,我们作为防御者的工作是在攻击者利用漏洞之前找到并修复我们代码中的漏洞。一些团队甚至将他们的框架连接到事件,例如漏洞赏金报告触发自动变体分析,安全审查触发扫描并附加候选发现,或者经过验证的漏洞更新静态分析工具以防止其在未来发生。

这项工作至关重要且风险很高。但如果做得好,它是一个更大、更有希望的转变的开始,我们将能够 在攻击者利用漏洞之前找到并修复漏洞。

如果您想保持与我们在网络安全方面工作的联系,请在此处注册我们的邮件列表。

致谢

作者:Eugene Yan 和 Henna Dattani,贡献者:Michael Molash、Abel Ribbink、Justin Young、Ben Morris、David Dworken 和 Hasnain Lakhani。这项工作借鉴了我们在 Anthropic 与模型合作处理安全的经验,以及我们的合作伙伴和客户分享的宝贵见解,我们对此深表感激。

‍

这篇内容对你有用吗?

反馈只用于改善内容筛选,不等同于收藏

分享这条资讯
分享海报
保存图片
iOS 也可以长按图片保存