Agent Skills 是供应链组件:Tessl 博客谈 AI 智能体技能安全
Agent Skills Are Supply Chain Components
Tessl 博客指出,Agent Skills 一旦被智能体信任,就能影响其读取内容、调用工具与信任边界,因此应被视为供应链组件。研究扫描约 4,000 个公开技能,发现可疑下载、凭证风险、类恶意行为与安全漏洞等问题。核心风险在于私有上下文、不可信内容与外部通信三者叠加,仅靠"先读一遍"不足以构成安全模型。
在 AI Native DevCon London 上,我从一个简单的问题开始:过去几个月里,谁给 agent 添加过 skill?有人举手。接着我请大家只在真正审阅过该 skill 并读过其 markdown 的情况下继续举手。
第二个问题才是这场演讲真正的起点。
我的演讲《你的 AI Agent 安装了恶意软件,因为一个 SKILL.md 让它这么干》讲的是我们正在围绕 agent skills 悄然构建的安全模型。一个 skill 看起来可能像文档。它可能是一个带有指令和元数据的 markdown 文件。但一旦 agent 信任它,这个 skill 就能影响 agent 读取什么、修改什么、调用哪些工具,以及把工作区的哪些部分视为可信上下文。
这使 skills 成为供应链组件。它们理应得到我们最终学会应用于包生态系统的同一种怀疑、审查、来源追溯、扫描和更新纪律。
我是从开发者安全工作的角度切入这个问题的。我在安全编码、JavaScript 安全、npm、PyPI 式生态系统问题,以及更近期围绕 skills、MCP 和编码 agent 的 AI 安全研究上花了大量时间。这些模式很熟悉:可复用组件迅速传播,审查习惯落后于采用速度,而攻击者会注意到那些最容易夹带信任的地方。
把这场演讲用作 Agent 上下文
Tessl 已把我的 AI Native DevCon 演讲变成了一个可供你的 agent 用作上下文的 skill。你也可以观看完整录像。

为什么 Skills 是一个供应链问题?
大多数人认为一个 skill 就是 SKILL.md。那只是这个对象的一部分。
一个 skill 通常有 frontmatter、正文、给 agent 的指令,有时还有辅助材料。它可能包含引用、资产、包、fixtures、辅助文件、安装脚本,以及人类审查者可能从未仔细阅读过的其他内容。在演讲中,我刻意使用了包生态系统的视角,因为开发者已经从 npm 和其他注册表中熟悉了这个故事。
当一个包被安装时,我们最终学会了询问关于维护者、版本、锁文件、完整性、签名、传递依赖、安装后行为和来源的问题。Skills 在这段旅程中处于更早的阶段。它们是可复用的 AI 组件,但其安全控制仍落后于其采用曲线。
在演讲中我讨论的研究里,我们扫描了来自一个公共 skill 生态系统的约 4,000 个 skills,发现了数量可观的问题:可疑下载、与凭据相关的风险、类恶意软件行为、滥用和安全漏洞。具体百分比不如趋势方向重要。Skills 的数量已经足够多、足够有用、发布也足够容易,因此供应链思维现在就必须到位。
错误在于说:“它只是 markdown 而已。”在 agent 工作流中,markdown 可以就是行为。
只读一次 Skill 不是安全模型
围绕 skills 的安全指南通常从类似这样的话开始:在启用前阅读该 skill,不要盲目信任第三方内容。这是明智的建议,但还不够。
第一个问题是深度。你只读了 SKILL.md,还是也读了辅助文件?你检查了引用的资产吗?你查找过该 skill 可能要求 agent 使用的脚本、fixtures 或包吗?你了解该 skill 运行时 agent 会拥有什么权限吗?
第二个问题是时间。即使你在安装时审查了该技能,你是否审查了每一次更新?你是否审查了团队内部共享的每一次变更?你是否在自主代理再次使用之前审查了每一个获取的版本?
第三个问题是信任是如何被授予的。许多编码代理会询问你是否信任某个工作区文件夹。一旦你回答是,该文件夹就可能成为边界。代理可能会将其中的文件视为指令、上下文或策略。如果不安全的技能位于其中,代理可能会继承你对文件夹的信任,并将这种信任应用于该技能。
这就是为什么我认为“先读一遍”并不是一个完整的模型。它依赖于在一个刻意追求更多工作自动化的流程中,人类保持完美的注意力。它还假设风险内容对人类审查者来说是显而易见的。在实践中,不安全的行为可能隐藏在自然语言指令、捆绑的参考资料或人们不会每次都检查的更新路径中。
风险是三重组合
演讲中的核心风险模型是私有上下文、不可信内容和外部通信的组合。
私有上下文是代理可以访问的数据:凭证、API 密钥、配置文件、仓库机密、客户数据、内部文档、收件箱、浏览器会话,或任何本不应离开本地任务边界的内容。
不可信内容是代理读取但团队未编写或验证的材料:未知贡献者提交的问题、电子邮件、网页、拉取请求评论、复制的提示、第三方技能,或从其他地方获取的仓库。
外部通信是代理将信息发送到边界之外的能力:打开网络连接、发表评论、创建问题、推送分支、发送电子邮件、调用 API、上传文件,或写入公共服务。
其中任何两项都可能带来风险。三者同时具备时,故障模式就会变得严重。一个能够读取私有上下文、消费不可信指令并进行外部通信的代理,其形态就是一个等待触发器的数据泄露。
这不仅仅关乎某一个代理产品或某一种工作流程。我使用了个人助理和编码代理的例子,因为同样的模式在整个领域中都存在。代理越有用,它们就越频繁地接触 shell、浏览器、电子邮件、仓库、API、内存、插件和第三方服务。从用户的角度来看,这些是功能。从攻击者的角度来看,它们也是影响行为的地方。
审批疲劳使边界变得更弱
人类审批通常被视为安全边界。有时确实如此。但当工作流程训练人们反复批准时,这就是一个脆弱的边界。
如果代理只请求一次权限,开发者可能会仔细阅读。如果它在例行任务中请求十次,开发者可能就开始一路点击通过。如果代理在宽泛的接受模式下运行,边界可能完全消失。在演讲中,我将此描述为从漏洞疲劳到接受疲劳的转变:安全控制仍然存在于界面中,但在实际工作流程中已不再有意义。
还存在一个混淆代理的问题。代理可能会要求人类批准某件听起来合理的事情,因为代理本身已受到某个技能、电子邮件或其他不可信内容的影响。人类看到的是来自他们所用工具的请求,而不一定是导致该请求的恶意指令。
这就是为什么问题不仅仅是“循环中有人吗?”更好的问题是,人类是否有足够的上下文、足够的时间,以及足够狭窄的权限请求,来做出真正的安全决策。
自然语言可能携带不安全行为
传统的供应链安全通常从代码扫描开始。这仍然有用,但技能增加了另一层,因为危险的部分可能是自然语言。
技能可以用简单的英语请求行为。参考文件可以编码只有在代理读取时才有意义的指令。内容可以被写成对人类看起来无害,但仍会被模型处理。即使是看似普通的辅助文本,如果代理拥有广泛的工具访问权限,也可能引导代理走向不安全的操作。
原始演讲包含了不安全技能行为的演示。我不会在这里重现其机制,公开记录出于防御目的被有意删减。教训并不依赖于操作细节:如果技能可以影响代理,那么仅将其作为 markdown 散文来审查是不够的。
一个例子类别是投毒输入:代理读取一封电子邮件、问题或网页,其中包含针对代理而非人类的指令。另一个是看似有用但要求代理获取或运行不安全内容的技能。另一个是隐藏或不明显的内容,人类在审查时可能错过,但模型仍会处理。
这些例子指向同一个根本问题。技能不仅仅是给人类的指令。它们是给可能拥有工具、上下文、记忆和行动权限的系统的指令。
技能扫描必须是行为性的
我还谈到了扫描器。如果技能正在成为供应链组件,团队会希望有办法扫描它们。这是正确的直觉,但扫描器必须理解问题的形态。
只查找明显字符串、命令或正则表达式匹配的扫描器会捕获一些不安全内容。它会错过其他情况,因为行为可以被间接描述、拆分到多个文件、隐藏在辅助材料中,或表达为意图而非字面命令。
这就是为什么我们研究了行为分析和分类驱动的扫描。扫描器应该问技能试图让代理做什么。它是否请求可疑下载?它是否处理凭据?它是否将数据导向外部目的地?它是否要求广泛的 shell 访问权限?它是否依赖隐藏或间接指令?来源是否清晰?是否有改变风险的辅助文件?
没有扫描器是完美的。基于模型的扫描可以捕获简单模式匹配遗漏的内容,但它仍然需要成为更广泛控制系统的一部分。重点不是用另一个黑盒取代审查。重点是让审查适应媒介。
注册中心在这里也扮演重要角色。在演讲中,我强调了注册中心侧的控制,因为分发点可以比单个团队更早地执行检查。如果注册中心扫描技能、检查来源、标记风险行为,并在安装前使安全信息可见,它就能改善所有人的默认路径。
像管理真实依赖一样管理技能
实际的应对方式是将技能作为真实依赖来管理。
从清点开始。了解技能分布在哪些位置:用户目录、项目文件夹、团队共享位置、注册表以及 CI 环境。如果你不知道你的智能体可以加载哪些技能,你就没有安全模型。
审查来源。谁发布了这个技能?来源是否可信?维护者是否变更过?技能是否包含支持文件?它是否要求智能体安装、获取、运行或传输任何内容?
在使用前和更新时扫描技能。不要将首次安装视为唯一的审查时机。上个月安全的技能在变更后可能变得不安全,尤其是当团队在内部共享和复用技能时。
限制权限。对于涉及私有数据或不可信内容的工作流,避免使用宽泛且未经检查的模式。在任务允许的范围内,尽可能收窄 shell 访问、网络访问、凭据访问和写入访问权限。
隔离高风险执行。当智能体需要处理不可信内容时,在沙箱或受限环境中运行它们。除非任务确实需要,否则将机密信息排除在工作区之外。
控制出站路径。如果智能体无法将数据发送到任意位置,那么完成三重威胁就会更加困难。日志记录、允许列表和网络边界都很重要。
将自然语言视为攻击面的一部分。以审查可能影响执行的代码同样的严肃态度,审查指令、引用、示例和捆绑文件。
保留证据。团队需要日志、版本追踪,以及能够回答哪个技能版本影响了某次运行的方法。没有这些,事件响应就变成了猜测。
技能需要依赖纪律
我并不是在主张团队应该停止使用技能。技能之所以有用,是因为它们为智能体打包了可复用的上下文和工作流。这正是它们需要纪律的原因。
包生态系统教会我们,复用改变了安全问题。一个组件不必很大就能产生影响。它只需要在足够多的地方被足够多具有足够访问权限的系统所信任,失败就会变得代价高昂。
智能体技能正在迅速达到这一点。它们易于编写、易于共享,也易于被智能体视为可信上下文。如果一项技能能够塑造智能体行为,它就属于供应链审查流程的一部分。
这就是我在 AI Native DevCon London 上提出的论点:不是说技能不好,而是它们足够强大,值得拥有真正的安全边界。要深入了解,请观看完整录像。
来源:Tessl Blog · tessl.io