你在用 Claude Code 或 Cursor 写代码,顺手装了一个看起来很实用的 Skill。

它的 SKILL.md 写得规规矩矩,没有可疑命令。配套的脚本你也扫了一遍,是正常的工具代码。两边都通过了你的检查,于是你放行了。

图片

问题是:它确实是恶意的。

恶意逻辑既不在那段 markdown 里,也不在那段脚本里——它藏在两者的配合关系里。markdown 负责诱导 Agent 准备好某个中间文件,脚本再去消费它,完成最后一步。你把它们拆开看,每一半都人畜无害。

这不是假设。一篇刚公开的学术论文,第一次把这件事系统地摆上了台面。

学术界第一次给"恶意 Skill"建了把尺子

这篇论文叫《MalSkillBench》,由南洋理工、四川大学、南开大学等机构联合发布。

研究团队把恶意 Skill 拆成三个正交维度——恶意逻辑从哪进来、最终想干什么、payload 怎么嵌进去——归纳出 3 类攻击向量、15 类恶意行为、108 个有效攻击单元,最后构建出一个含 3,944 个恶意样本、4,000 个良性样本的数据集。

最值得注意的,是它定义的三类攻击向量里的第三类。

第一类是 代码注入(CI):恶意逻辑直接写在脚本或 markdown 的代码块里,最接近传统恶意包,凭证窃取、远程执行、反弹 Shell 都在这一类。

第二类是 提示注入(PI):恶意逻辑藏在 SKILL.md 的自然语言说明里,不一定带代码,而是让 Agent 自己去执行危险动作,甚至改掉 Agent 的身份和安全边界。

第三类是 混合攻击(MIXED):把攻击链拆成两段,markdown 负责诱导 Agent 生成或下载某个中间对象,脚本再消费这个对象完成攻击。论文说得很直白——这种攻击只有在 Agent 同时遵循 markdown 指令、又执行了协调脚本时才会显现。

换句话说,它的恶意性不在任何一个文件里,而在文件之间的关系里。

图片

为什么你现有的检查方式,正好被它绕开

回想一下你怎么审一个第三方包、扩展、Skill:扫代码特征,比对已知恶意模式,看有没有硬编码凭据、可疑域名、危险系统调用。背后是 SAST、SCA、病毒库匹配——全都是静态分析。

静态分析有个隐含前提,恶意是能在某段代码里被单独揪出来的特征。传统恶意包时代,这个前提成立。

MIXED 攻击专门打掉了它。恶意拆成两个本身合法的部分,扫描器无论扫哪一半都报不出问题。你不是没扫,是扫了也看不见。

这就是论文反复强调“runtime-verified”(运行时验证)的原因——只有让 Skill 在 Agent 环境里真的跑一遍,看它实际触发了什么行为,才能判定是不是恶意。看静态文件,得不到答案。

而这恰恰是大多数企业当下的盲区:开发者每天在 AI 编程工具里随手拉取 Skill,但准入这道关,要么没有,要么还停在“扫一遍代码”的旧逻辑上。

图片

拦截要发生在"进门那一刻",不是装完之后再扫

就算你有能力识别恶意 Skill,识别的时机也很关键。

私有制品仓库、定期 SCA 扫描确实能发现问题,但发现得太晚。等下一轮扫描跑起来,恶意包早就落地到开发者工位、进了 CI/CD 流水线。情报是有的,管控没跟上,中间这段时间就是敞开的。

业界正在采用的另一种思路,是把防护点直接挪到供应链入口:每个被拉取的开源组件、第三方依赖、AI 工具包,在抵达开发环境之前先过一道情报核验。命中已知恶意当场拦下,白名单放行,未知样本实时查询——恶意代码"进门"那一刻就被卡住,而不是进门之后再去翻它干了什么。

塞讯软件供应链防投毒智能网关(CyriGate)就是这个思路的落地:作为制品仓库代理部署在供应链入口,把开发者工位、CI/CD 流水线,以及 Claude Code、Cursor 这类 AI 编程工具都设成卡点,威胁情报库覆盖传统软件包与 AI Skills 全品类。

图片

但要说清边界,网关拦的是进门。像 MIXED 这种靠运行时行为才暴露的攻击,准入核验之外还得在真实环境里把攻击剧本跑一遍、验证防线挡不挡得住——这是供应链情报到执行验证之间该闭合的另一环。

第一步,是别让恶意 Skill 在你毫无察觉时就进了开发者的机器。

回到最开始那个场景

你扫了 markdown,扫了脚本,两边都干净,于是放行。

这套动作在三年前没问题。但当攻击者学会把恶意拆进文件之间的关系里,“分别检查每个文件”这件事本身,就成了被利用的漏洞。

值得问自己一句:你现在审第三方 Skill 和扩展的方式,是为哪个时代设计的?是不是上个世纪的? 你所在的团队,AI 编程工具的包准入这道关,现在是怎么把的?留言聊聊。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐