把YARA-L常见生成错误写进Agent Skill
文章列举AI生成YARA-L规则时常见的枚举、字段类型、事件关联和聚合错误。作者将这些约束整理成公开的Agent Skill,为模型编写检测规则补充语言知识。
AI 深度解读
让 AI 写安全检测规则,最麻烦的是它经常写出「看着很像,实际跑不通」的代码。作者把 YARA-L 的常见错误、交付规范和离线检查脚本打包成 Agent Skill,希望把这些低级错误挡在人工审核之前。
这套做法对日常 AI 编程也有启发:专业知识不能只停留在提示词里,还要变成可执行的检查。但标题里的「真的能编译」需要打个问号,作者也承认,最终能否编译,仍要由 Google SecOps 编译器确认。
为什么看起来正确的规则会接连出错
作者列出的五类错误,都属于熟悉语言的人容易发现、通用模型却会反复踩的坑。
事件类型写成 metadata.event_type = "LOGIN",实际枚举是 USER_LOGIN;端口写成 target.port = "443",但端口要求整数;多个事件变量没有在 match 中通过共享占位符关联,可能无法编译,也可能把所有事件互相配对;带有 match 的规则在 outcome 中直接使用原始事件字段,缺少 count()、array_distinct() 等聚合;还有更隐蔽的一类:编造听起来合理、解析器却没有输出的 UDM 字段。
UDM 可以理解为日志归一化后的事件数据模型。字段名合法,还不代表自己的日志源一定填了它。
作者的解决办法,是把这些约束写进 SKILL.md,再配上参考资料、示例和脚本。Agent 根据任务描述加载对应 Skill,而不是每次都靠用户重新解释规则。
原文称,Anthropic 在 2025 年 12 月将这种格式作为开放标准发布,Claude Code、GitHub Copilot、OpenAI Codex、Gemini CLI 和 Cursor 都能读取。这里应区分两件事:格式可以复用,具体客户端是否能执行脚本、如何发现 Skill,仍与运行环境有关。
交付规则时,为什么还要交付待核验清单
这套 Skill 接收威胁描述、ATT&CK 技术、Sigma 规则或 SPL/KQL 查询,按一个 8 步流程处理。原文没有逐项展开这 8 步,但明确规定了六项交付物:
- 用一句话解释检测逻辑。
- 提供完整的 YARA-L 2.0 规则,包含
meta、outcome和$risk_score。 - 列出需要对照自家解析器核验的 UDM 字段。
- 给出要创建的引用列表、数据表及示例行。
- 各提供一个应该触发和不该触发的测试用例。
- 指出两个最可能的误报来源及调整办法。
其中最有价值的是第三项。同样是登录失败,一个数据源可能写成 BLOCK,另一个可能写成 FAIL。Skill 要求用 // VERIFY: 标记不确定字段,让使用者知道部署前该查什么。
作者用设备代码钓鱼说明这套流程。原文引用 Microsoft 在 2025 年 2 月披露的 Storm-2372 活动:攻击者发送假的 Teams 会议邀请,让受害者在真实 Microsoft 登录页输入代码,随后取得有效令牌。
对应规则检测「不在批准名单内的账号成功使用设备代码登录」。它使用 USER_LOGIN 和 ALLOW,把日志类型写为 AZURE_AD,把认证协议判断写为 $e.additional.fields["authenticationProtocol"] = "deviceCode" nocase。后两处都带有核验提示,不能直接假定适用于自己的解析器。
批准名单放在 %device_code_approved_users.userid 数据表中,SOC 更新 CSV 即可调整例外。match: $user over 1h 按用户归并登录事件,作者举例,一个用户登录五次,得到一条告警及 $signin_count = 5。
规则设定 $risk_score = 75,使用 count() 统计次数,用 array_distinct() 收集 IP、应用和国家信息;元数据包括 T1528、rule_version = "1.0" 和 yara_version = "YL2.0"。这些是示例的具体选择,原文没有证明风险分数 75 适合其他团队。
离线检查能挡住什么,又挡不住什么
仓库提供四种示例:certutil 下载载荷的单事件规则、暴力破解后成功的序列规则、EDR 停止后未恢复的缺失事件规则,以及上述数据表查询规则。
为了让 Agent 能检查自己的输出,作者还提供了无依赖 Python 脚本 lint_rule.py。下面这段保留了原文的失败输出,展示它具体检查哪些问题:
$ python3 scripts/lint_rule.py bad_rule.yaral
[FAIL] bad_rule.yaral
error: sections out of order: ['events', 'meta', 'outcome', 'condition']; expected order ['meta', 'events', 'match', 'outcome', 'condition', 'options']
error: unknown metadata.event_type value "LOGIN"
error: integer field ending '.port' compared to a quoted string
error: multiple event variables but no match section
error: absence condition (!$var) requires a match section
warning: no $risk_score in outcome
注意最后的 warning:Skill 要求 Agent 修复全部错误,并把警告继续交给用户,不能把检查通过包装成没有问题。
离线 lint 通过,只说明这些检查没有发现错误,不代表规则已经编译成功。
安装位置也因客户端而异。Claude Code 的个人和项目目录分别为 ~/.claude/skills/、.claude/skills/;GitHub Copilot/VS Code 对应 ~/.copilot/skills/、.github/skills/;Codex 和其他客户端在原文中对应 ~/.agents/skills/、.agents/skills/。Claude.ai 则需要将 yara-l-authoring 文件夹压缩后作为自定义 Skill 上传。
作者给出的试用任务是:检测 30 分钟内 10 次登录失败后出现一次成功。生成以后,流程还没结束。
我的判断
我认同作者把「规则说明、固定交付物、自动检查、人工审核」连起来的做法。相比只让模型参考几份示例,脚本能对部分错误给出明确反馈;相比直接拒绝所有不确定内容,// VERIFY: 又能保留草稿价值,让人工集中核验关键位置。
但这仍是一套有待更多验证的工程实践。原文没有给出测试集规模、编译通过率、误报率,也没有比较使用 Skill 前后的结果。能确认的是作者展示了生成示例和检查能力,不能据此认定已经稳定解决 YARA-L 生成问题。
数据表管理例外也有前提:名单需要有人维护。正常的 Azure CLI、PowerShell --use-device-code 登录,以及会议室、IoT 设备,都可能触发相关检测。语法检查不会替团队判断这些业务行为是否合理。
作者建议先关闭告警保存规则,对过去 7 到 30 天做历史回溯检索;中等严重级别规则若每天超过 20 次检测,就继续调优,再让分析师审核 10 条样本。这些数字属于作者的上线经验,原文没有给出对照数据,不能当成通用标准。
能拿来做什么
- 如果团队正在使用 Google SecOps,可以先拿「30 分钟内 10 次失败后成功」这样的明确任务试跑,逐项核验字段和正反用例,再送入编译器检查。
- 维护检测内容时,可以把经常变动的批准用户移入数据表,同时明确名单负责人,避免例外配置长期无人更新。
- 在日常 AI 编程中,可以借鉴这套交付约定:除了代码,还要求列出待核验假设、正反用例和检查结果。迁移时应采用目标项目自己的校验工具。
- 上线前可以参考作者的回溯流程,但应根据日志量、告警处理能力和漏报代价调整阈值,保留人工审核这一关。