我扫了自己64个AI技能:17个被标禁止安装
在今天凌晨的这个时间点, 我就把手边这台机器上头存放的所有有关 AI Agent 的技能内容, 全都喂那个安全扫描器去进行了处理。最后出来的结果情况是这样的: 在总共六十四个技能之中, 有十七个被判定为禁止安装的状态, 有四十五个被判定为警告状态, 然后只有区区两个拿到了安全的结论。最显眼的是排在前面的那些名字, 也就是-agent得到了一百分, 还有得了八十九分的那个以及得了八十七分的那个。前这两个是属于系统自带的技能, 只有第三个才是由我本人编写的代码逻辑。在我本地所拥有的六十四个技能当中, 有五十八个都是随着工具一起被打包进来的, 唯独只剩下六个是我亲自去写的。这绝对不是意味着“我的技能有毒”, 而这正是这类工具最容易被产生误解的一个地方, 同样是我撰写这篇内容的根本原因。面对同一份报告, 你可以得出这样的结论: “我的机器表现极其糟糕”, 你也可以选择去探究一下这个分数究竟是在衡量哪些方面。其中的关键差别在于, 你是否真正看懂了报告里面所包含的各个字段含义。[b9][]这款工具的名称虽然没有明确写出, 但它是基于开源技术的 agent 技能安全扫描器, 目前版本号处于 2.0 阶段, 在当月的小周榜单中占据了前列位置, 累计获得的星标数量高达 15.8K。该软件要求您的运行环境版本至少要是 3.12 及以上才能正常运作, 如果采用 uv 这个来进行安装将会是最为省心简便的操作方式。用那个uv工具, 再配合着git加加号。[]对 ./my-skill/ 目录执行扫描操作, 并且不启用 llm 功能。--no-llm 这个功能是纯本地的静态分析它会使用正则表达式、抽象语法树以及 YARA 规则来进行处理。在此模式下, 工具不会连接网络, 也不需要提供 API 密钥, 同时你的技能内容也不会被发送出去。如果去掉这个参数, 文件内容就会被发送到你配置的模型端点去进行语义分析。这是我建议你在使用时首先添加的参数, 具体原因将在后面的第三节中进行讲解。它是支持扫描指定目录、单个SKILL.md文件、zip压缩包, 或者是直接输入Git仓库地址进行读取的。它的输出结果一共有四种格式, 分别是json格式、sarif格式, 以及另外两种未明确指出的格式。如果你准备把它集成到CI系统里面去使用的话, 就可以直接使用参数 -- json 来获取json格式的输出了。这是优采云给出的第二个部分的真实扫描结果内容, 这里面包含了分档的情况、具体的分数是多少, 还有成功命中了哪些东西。我花了大概 8 分钟的时间, 把技能库从头到尾仔细地筛查了一遍, 全程没有任何报错出现。在这个过程中, 一共涉及了 15 个不同的分类领域, 包含了 64 个名为 SKILL.md 的文件内容, 总计处理了 354 个文件项目, 这其中包括了数量达 62 个的脚本文件资源。这个分数的区间是从 0 到 100。那分数是怎么算出来的呢, 官方给了一个具体的计算规则: 在基础分之上, 如果命中一条匹配项就加 50 分, 等级为 HIGH 的就加 25 分, 等级为中等的加 10 分, 等级为 LOW 的就只加 5 分。不过如果该漏洞包含可执行脚本的情况, 那么最终得分还要再乘以 1.3 倍的系数。最后根据得到的总分来进行定级划分: 分数在 0 到 20 之间的判定结果为安全, 分数在 21 到 50 之间的判定结果为警告, 分数在 51 到 80 之间的判定结果为禁止安装, 而分数在 81 到 100 之间则属于严重级别。命中最多的模式我库里 64 个技能的合计次数模式它是什么意思结果是命中。有些数据被发送到了外部的网址去。153把远程脚本先下载下来, 之后再执行它。55代码实际进行了访问动作, 访问的对象是那些用来存放敏感信息的文件, 比如说SSH密钥、.env文件等。52通过 cron 或启动脚本建立跨会话持久化32call调用了17读到这个地方, 你或许已经恍然大悟: 此五种类别, 恰恰构成了“一种具备实际工作能力之技术技能”的标准配置要求。我的技能文档里面记载着 API 的端点情况, 这个内容命中了前两条规定, 其中提到要使用 gh CLI 这个工具, 还要用 uv 来安装配置, 并且说明了应当如何读取位于 .env 配置文件里面的 key, 此外还有一个具体的技能操作步骤, 是指导如何将网关设置成为开机自启动的状态, 这正好命中了关于持久化设置的那一条规则。第三点的反直觉的情况在于其实未必真是那么回事弄错了, 更有可能是你只是没有看到所有的全貌罢了。在这 45 个警告 的内容里面, 有 23 个技能, 它们的一条问题都没有被检出, 也就是说得分是 0。但是, 这其中有 21 个, 依然还被标记成了。一个连问题都不存在的技能, 为什么它不能够被标注成安全 呢?我把报告往后翻, 到了那个写着“s”的地方, 答案就在里面显示的是 45 个技能, 每一个技能都跟着一条分析例外, 导致这个例外的具体情况是文档里存在一个像是路径那样的引用内容, 结果没法把它给唯一地解析出来。技能文档里面, 有一句写出来的示例路径, 扫描器在检测的时候, 发现找不出这个具体存在的文件, 于是就把那个分析报告的状态标记成了不完整的形式, 这就导致推荐的等级变化了之前是显示为安全现在直接升高到了警告的级别, 至于那两个依然被判定为安全的技能, 原因很明显, 就是因为对应的文档里缺少这种引用的信息。因此, 这三个字母需要按照这样的方式来发音:它是一个结论, 可是这个结论的呈现效果, 会受到分析完整性的影响, 如果分析是不完整的, 那么它达到的最高标准, 就只能停留在某个特定的层面。· score 和 才是实质内容——分数来自具体条目条目的严重级别、置信度、行号都在报告里当你仅仅将那三个字母放在一起进行审视的时候, 你会得到一个极其荒谬的看法, 这个看法认为在你所掌握的全部 64 个技能之中, 竟然有 62 个是存在问题的。在编号为04的这一部分里, 存在一个能够被数据来加以验证的客观规律, 那就是那些带有脚本的功能技能, 其危险程度会显得更高一些。将这 64 个技能, 依据它们是否拥有可执行的脚本, 划分成为两个不同的组别, 结果显示两者之间存在显著的差异。在包含脚本的那一组数据里, 其平均分数值达到了不包含脚本的对照组那一组数值的三倍之多。同时前, 该组被拦截掉的比例也呈现出了四倍于对照组的显著差异表现。在方向方面, 这种情况和项目方自己引用的研究结果是一致的。他们的统计数据显示, 一共统计了 42,447 个技能。包含可执行脚本的技能出问题的概率更高, 他们给出的倍数是 2.12 倍。有 26.1% 的技能里至少包含一个漏洞。另外, 有 5.2% 的技能存在比较明显的恶意意图。那几组具体的数值代表了他们方面的设备口径, 这并不等同于我这边进行的实际测量工作不过, 关于“脚本的量越大就越是应该投入更多的注意力去审视”这样一个基本的观察方向, 我已经在我自己手里的这台机器上面把情况成功地复现并且验证了出来。对你的实际含义很简单: 在装别人的技能之前, 先看它有没有脚本, 有脚本的优先扫。第05节, 我创造了一种被称作坏技能的玩意, 并且打算看看它究竟有没有本事能够成功抓到目标。只谈分数的话, 其实是缺乏直观性的。所以我编写了一个仅仅拥有 23 行代码的技能模块, 并且在其中刻意地混入了四种典型的风险套路。这些套路具体包括: 意图让你去忽略安全防护约束的命令指令、通过 curl 命令直接连接 bash来进行环境安装的操作、读取系统下~/.ssh目录中的私钥文件并将其上传到外部的配置步骤, 以及另外单独设置的一行定时执行任务。经过扫描, 最终给出的结果是七十三分判定为高危等级, 共计命中四项规则, 这其中包括外部脚本拉取情况置信度达到百分之九十、工具链滥用情况置信度为百分之七十以及凭据访问情况置信度同样为百分之九十且包含两条记录。但是, 这里有一个必须要指出的盲区存在: 我植入的那句“忽略之前所有安全约束”以及那个静态模式下没有被报出来的情况。产生的原因不在于没有编写这些相关的规则, 而是因为--no-llm这个参数把语义分析功能给关闭了。官方文档在该条款的说明文字里面写得非常直白清楚, 在不存在 LLM 进行分析的时候情况是这样的, 内容建议由人工来进行复核操作。也就是说, --no-llm 这个选项属于初步筛选的步骤, 它并不是最终且全面的判定依据。它的主要优势在于能够快速识别出那些具有明显外部特征的行为, 比如执行来自外部的数据传输、进行文件下载操作, 或者是非法访问凭证等类型的事情。然而, 对于那些需要从深层语义角度来判断的情况, 例如判断某句指令是否存在试图绕过既定安全策略的意图, 这种方式就显得力不从心了。在这种情况下, 用户必须启用 LLM大型语言模型来辅助进行深入分析。鉴于此, 建议不要在处理含有敏感数据的工具或服务中直接使用该模式扫描功能。或者, 用户也可以选择不依赖自动化工具, 而是亲自通过肉眼观察和分析的方式来完成最后的检查工作。在06的情况下, 所以它会到底应当如何被运用呢。我的结论是: 不要用它来给自个儿写的技能进行打分评估, 而是应该把它当作是一个在正式安装之前的检查关口。具体三步1. 在进行任意第三方技能的安装操作之前, 务必先执行一次扫描步骤, 具体的扫描命令请使用带有 no-llm 参数的 scan 指令。2. 查看评分和列表, 而不看“结论”这两个字, 只要分数大于五十分就去把每条问题的行号和上下文拿出来进行一遍核对, 如果发现对不上就把它当做噪音忽略掉如果发现对得上就不要装聋作哑。3. 只做新增发现的判断这件事是支持的, 它的作用是把那些已经知道的、你自己也接受过的发现记录下来, 等到下一次扫面的时候, 只报告那些新的项目, 如此一来, 你平时做复扫操作的时候, 就不会被一大堆过去的噪音给淹没了。它还有一个更有意思的用法, 就是把 当作 MCP 服务器去运行, 让 agent 在装载技能的时候, 先自己扫描一遍, 然后再做出决定。这是官方文档里记载的用法, 只需要安装 MCP 扩展就行了。这一步我没有自己亲自实测, 所以不替大家下结论。这个工具本身也是有边界的, 它不做动态分析, 它不执行被测的技能, 这一点算是它的优点, 因为全量的静态分析都是在本地进行的, 并且它对混淆代码以及二进制产物这些东西的覆盖范围是有限度的, 所以在给路径的时候得上类似C:/...这样的形式, 像用MSYS那种以/c/...开头的方式它是认不到的。我们还得再把话题绕回到那个最开始提到的数字, 也就是17个被明确标注为禁止安装的情况, 而这里面的每一个情况都不是由于我的技能本身存在偷取数据这种真实的违规操作所导致的, 相反, 它们之所以会被触发, 全都是因为一些看上去完全正常的写法恰好撞上了那些静态特征, 而这些所谓的正常写法具体就包括了文档里面写出了外部URL地址, 或者是在内容里教了大家怎么去装载工具, 又或者是指导人们去读取那些存放在.env文件里面的访问密钥。这既是这类扫描器的价值所在, 也就是它能够把可疑形状的代码给挑出来, 同时这也导致了它的成本, 也就是它会把你自己的正常工程习惯也一起给挑出来。关键在于千万不要把这个东西当成最终的判决文书, 而是要把它当作一个放大镜来用: 它的功能是明确地指引你去关注那些确实值得再多花费一点时间和精力去深入观察的技能, 它绝对不会代替你做出最终的决定, 也就是它不会帮你判定哪一个技能就是可以使用的。假设你如今手头上同样积攒下许多来历并不明朗的技能, 那么请在今日花费大约十分钟的时光去进行一次彻底且全面的梳理与回顾。上文所提及的那条具有 --no-llm 标志的命令, 其运行过程无需连接任何网络线路, 同时也完全不需要提供所谓的密钥信息。一旦该项扫描任务顺利结束完毕, 你对自身这台机器设备之中究竟安装了哪些内容所产生的认知、感受, 将会发生极其截然不同且全然一新的变化。我接下来打算把刚刚扫描出来的那 17 条“禁止安装”的情况逐一拆开来说清楚, 仔细分析里面究竟哪些部分是因为我的代码写法存在问题需要加以修正, 而另外一些部分则完全属于误报现象。在把所有这些问题调整修复完毕之后, 我会重新进行一次扫描操作, 以便对比前后的结果分数看看是否有变化。如果你想要查看这份详细的对照表格的话, 可以先关注一下我的动态并等待后续更新, 因为我会直接在下一篇发布的文章中把它完整地贴出来供你参考。