mcpField
C
create-rule

create-rule

github.com/seqra安全17058 次安装3 天前更新
代码仓库

关于 create-rule

create-rule 是面向 OpenTaint 规则编写者的安全技能。它检查已有的源或汇规则覆盖,为缺失项创建库规则,并通过测试样例验证。

主要功能

  1. 01查找已有规则覆盖
  2. 02创建带标签的源或汇规则
  3. 03编写测试连接并运行测试
  4. 04更新规则跟踪文件

适用场景

  1. 01为软件包补充源或汇覆盖
  2. 02在修复模式下调整已标记规则
  3. 03用样例检查规则行为

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/seqra/opentaint --skill create-rule

安装后在 Claude Code 中输入/create-rule确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
debugging.md
java.md
scripts/
check-test-result.py

详细介绍

技能:创建规则

OpenTaint 是一种全程序、过程间、字段敏感的别名分析引擎。它已经能够沿着可见的应用代码、调用、别名和各个字段传播;自定义规则和近似规则只用于建模指定的源、汇或不透明方法边界。编译时常量和字面量不携带污点,因此输出仅为常量的源或载体不会引入污点。

一个单元会指定要检测的源或汇成员。如果现有内置规则或项目库规则已实现该边界,就识别并使用该规则;否则编写自定义规则,然后针对其测试项目验证该单元。每条选用或创建的源规则都必须带有该单元的 untrusted-data-source 标签;每条选用或创建的汇规则都必须带有其单元组的 *-sink 标签。生产环境中的关联使用这些标签,只有在需要新建汇标签时才会稍后组装。

输入

由调用方提供;省略时使用默认值。仅当缺少必填输入且没有合理默认值时才进行询问

  • project-root(可选)— 目标项目的根目录。Opentaint 会将所有分析产物保存在固定的 <project-root>/.opentaint/ 目录下,因此下文中的每个 .opentaint/... 路径都会解析到该目录。默认值:当前目录
  • language(必填)— 此项目的目标语言及语言专属说明
  • side(必填)— sources 或 sinks;单元所属的一侧。它决定单元文件、示例风格和测试子项目
  • unit(必填)— 用于标识单元的 <package-kebab>。其规范和跟踪记录位于 .opentaint/tracking/rules/<side>/<unit>.yaml;测试项目位于 .opentaint/test-projects/<unit>/<side>,编译后的模型位于 .opentaint/test-compiled/<unit>/<side>
  • fix-target(可选)— 主扫描标记出的已创建规则 <path>#<id>,以及需要修正的误报或漏报。设置后,应收窄或扩大该条规则,而不是从单元开始编写

工作流

1. 检查现有覆盖

浏览内置库规则和 .opentaint/rules,判断是否已有规则与单元中的每个条目匹配。如果有,不要编写重复规则:在 .opentaint/tracking/rules/<side>/<unit>.yaml 中将其 rule_id 设为 <relative-yaml-path>#<rule-id>。此字符串仅用于跟踪记录。不要向任何生产规则添加 rule 引用;生产环境中的关联仍基于标签,稍后再编写。以下命令会打印内置规则根目录。使用语言参考浏览这两个根目录,并按条目的精确语言专属标识符搜索:

opentaint health --rules

阅读 .opentaint/tracking/rules/tags.yaml。源单元必须带有 tag: untrusted-data-source;每个汇单元组的规则都必须扩展其现有或新注册的一个 *-sink 标签。

在修复模式下,不要从单元开始编写:直接转到那条被标记的规则,按照步骤 4 中有关误报或漏报的指导调整规则,重新运行本侧的测试,然后停止;单元的其他条目保持不变。否则,如果条目已带有 rule_id,就继续使用这些记录的实现,仅为仍未覆盖的条目编写规则。如果单元只完成了部分阶段(部分阶段为 done,其他阶段未完成),就基于磁盘上的现有产物从第一个未完成阶段继续,而不是重新开始。

2. 编写库规则

根据单元的准确成员标识符、记录的签名及相关声明元数据推导每条规则的模式。将污点值绑定到 $UNTRUSTED,并在库规则上添加单元/组标签。汇点标签属于整个语义组,而不是单个方法。一条规则可以涵盖组中的多个方法,也可以有多条规则携带相同标签。规则形式和位置请参阅语言参考。

对于 side: sinks,遍历 groups:确保 groups[].sinks 下的每个方法都有对应的实现 rule_id,并将外层的 groups[].tag 添加到你创建的每条自定义规则上。对于 side: sources,使用单元顶层的标签。

3. 编写测试连接规则

库规则本身不会产生任何结果——要测试它,需在临时测试连接规则中将它连接到通用污点标记。针对该侧,在测试项目的标记规则中编写一条连接规则,一端引用通用标记,另一端引用为该单元选定的每个库 rule_id,这样正向样例中的污点值就会从标记流向规则(汇点侧),或从规则流向标记(源点侧)。测试连接规则只存在于测试项目中,绝不能放在被扫描的规则树中。其形式、命名和位置请参阅语言参考。

4. 测试直至成功

直接以前台阻塞命令运行规则测试,并等待其退出——绝不要将测试放到后台运行或使用 Monitor。加载你的库规则、测试连接规则和标记规则,然后反复迭代,直至所有样例都通过:

opentaint test rule run .opentaint/test-compiled/<unit>/<side> \
  -o .opentaint/test-results/<unit>/<side> \
  --ruleset .opentaint/rules --ruleset .opentaint/test-projects/<unit>/<side>/test-rules \
  --passthrough-approximations .opentaint/pass-through

test rule run 会自动加载内置规则,因此只需传入你的自定义规则集。按原样应用直通近似规则;即使为空也无妨。使用随附脚本读取结果——它会显示通过/失败计数并列出失败样例,因此你无需手动解析 JSON:

uv run <skill-dir>/scripts/check-test-result.py <unit>/<side>

根据报告的结果修复:

  • falseNegative → 匹配范围过窄,应扩大范围,并确认元变量名称在各分支之间以及 refs 和 on 之间一致
  • falsePositive → 匹配范围过宽,应添加排除条件或净化器
  • skipped / disabled → 规则未被测试;修复样例的 rule-test.yaml 入口或 rule-id,或者启用该规则

各类修复对应的具体模式运算符请参阅语言参考。

5. 正向样例无法收敛时升级处理

如果修复规则约 3 次后正向样例仍未通过,原因可能不是编辑规则就能解决的。按照 references/debugging.md 定位原因,然后将 stages.tests_passing: pending 保持为待处理状态,并根据 Output 报告问题,而不是盲目修改。

输出

交付物
  • .opentaint/rules 下的自定义库规则文件
  • .opentaint/tracking/rules/<side>/<unit>.yaml — 已更新该单元的条目(参见 Tracking)
摘要
  • 实现库规则的 ID,并注明哪些是内置规则、哪些是新建规则;该侧的一行测试摘要;以及实际使用的完整 test rule run 命令
  • 如果在第 5 步受阻:将 stages.tests_passing 保持为待处理状态,并说明原因 —
    • 失败样例的数据流中有库方法被丢弃 → 列出需要建模的方法,以便在重新分派前进行近似处理
    • 没有被丢弃的方法,且没有明确的规则原因 → 未能收敛,需由编排器介入

跟踪

此技能会为每个单元条目记录其实现规则的 rule_id,以及该单元的 stages.tests_passing。rule_id 是 <relative-yaml-path>#<id> 定位符,指向为该条目创建的自定义库规则,或已证明能够覆盖该条目的现有内置库规则。保留源单元顶层的 tag 和每个接收器 groups[].tag,这些标签是作者契约。被阻塞的单元应保持 tests_passing: pending。

.opentaint/tracking/rules/sources/<package-kebab>.yaml — 每个软件包一个源单元(一个依赖项可以跨越多个软件包),文件以该软件包命名,并将 . 替换为 -。tag 始终为可复用的 untrusted-data-source 组。dependencies 指明软件包所属的依赖项;sources 中的每个条目都是一个入口点 { method, signature, note, rule_id }(method 和 signature 使用计划中精确的特定语言标识符);stages 跟踪该单元的规则编写进度;如果该单元无法通过测试,则在其下添加 blocker 字符串。请通过注释明确说明

dependencies:
  - <dependency-id>
tag: untrusted-data-source
sources:
  - { method: "<qualified-member>", signature: "<language-signature>", note: untrusted message payload, rule_id: null }
stages:
  test_project: pending
  tests_passing: pending

.opentaint/tracking/rules/sinks/<package-kebab>.yaml — 每个软件包一个接收器单元(一个依赖项可以跨越多个软件包,每个软件包各自有一个单元),文件以该软件包命名,并将 . 替换为 -。dependencies 指明软件包所属的依赖项。groups 按可复用的接收器标签划分该软件包的危险操作;每个组的格式为 { tag, sinks },每个接收器的格式为 { method, signature, note, rule_id }。标签属于组,绝不属于单个方法:一条规则可以覆盖多个方法,也可以有多条规则扩展同一漏洞类别。method 和 signature 使用计划中精确的特定语言标识符。stages 跟踪该单元的规则编写进度。请通过注释明确说明

dependencies:
  - <dependency-id>
groups:
  - tag: path-traversal-sink
    sinks:
      - { method: "<qualified-member>", signature: "<language-signature>", note: writes data to an untrusted path, rule_id: null }
stages:
  test_project: pending
  tests_passing: pending

约束

  • 库规则必须包含 options.lib: true 和 severity: NOTE
  • 创建的源规则必须带有 untrusted-data-source 标签;创建的接收器规则必须带有其所属接收器组已注册的 *-sink 标签
  • 测试连接必须包含 metadata.cwe 和 metadata.short-description
  • 在测试连接中,refs 和 on 子句中的元变量名称必须一致,否则连接无法建立。在每条库源规则和接收器规则中,将受污值绑定到 $UNTRUSTED
  • 测试连接的 rule 路径相对于规则集根目录:标记规则在测试项目的规则目录下解析,库规则在内置或自定义的扫描规则树下解析
  • 规则 ID 必须全局唯一
  • 自定义库规则放在扫描规则树中;测试连接只能放在测试项目的标记规则中
  • 绝不扫描主项目模型
  • 绝不尝试编辑测试项目

注意事项

  • 如果你认为测试项目有误,请将其退回上游
  • 如果某个正向测试因库方法丢弃了污点而无法通过,这不是规则错误——应将其作为近似处理问题上报(参见第 5 步),不要为了强行通过而扩大规则范围
  • 生成的规则文件中不要包含注释

评论

支持 Markdown