create-rule について
create-rule は、OpenTaint のルール作成向けセキュリティスキルです。既存のソース/シンクを確認し、不足するライブラリルールを作成してテストサンプルで検証します。
主な機能
- 01既存ルールの適用状況確認
- 02タグ付きソース/シンクルールの作成
- 03テスト用ジョインの作成と実行
- 04ルール追跡ファイルの更新
活用シーン
- 01パッケージのソース/シンク対応追加
- 02修正モードで対象ルールを調整
- 03サンプルによるルール動作の確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ seqra/ opentaint --skill create-ruleインストール後、Claude Code で/create-ruleを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/debugging.mdjava.mdscripts/check-test-result.py詳細
ルールの作成
OpenTaint は、プログラム全体を対象とする、手続き間かつフィールドセンシティブなエイリアス解析エンジンです。可視のアプリケーションコード、呼び出し、エイリアス、個々のフィールドをすでに伝播の対象としており、カスタムルールと近似は、割り当てられたソース、シンク、または不透明なメソッド境界のみをモデル化します。コンパイル時定数とリテラルは taint を持たないため、出力が定数のみのソースやキャリアは何も導入しません。
ユニットでは、検出対象のソースまたはシンクメンバーを指定します。境界をすでに実装している組み込みルールまたはプロジェクトライブラリルールがあればそれを特定し、なければカスタムルールを作成して、ユニットをテストプロジェクトで検証します。選択または作成するすべてのソースルールには、ユニットの 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 タグを1つ付けます。
修正モードでは、ユニットをもとに新しいルールを作成せず、フラグが立てられたそのルールに直接進み、手順4の偽陽性/偽陰性に関する指針に従って調整し、この側のテストを再実行して終了します。ユニットのほかのエントリーには変更を加えないでください。それ以外の場合、エントリーにすでに rule_id があるときは、その記録済みの実装を引き継ぎ、まだ適用範囲に含まれていないエントリーだけを作成します。ユニットの作業が途中まで進んでいる場合(一部のステージが done で、ほかは未完了の場合)は、最初からやり直さず、ディスク上の既存アーティファクトを使って、最初の未完了ステージから続行します。
2. ライブラリルールを作成する
各ルールのパターンは、ユニットの正確なメンバー識別子、記録されたシグネチャ、および関連する宣言メタデータから導き出します。汚染された値を $UNTRUSTED にバインドし、ライブラリルールにユニット/グループのタグを付けます。シンクタグは個々のメソッドではなく、セマンティックグループ全体に付与します。1つのルールで複数のグループメソッドをカバーでき、複数のルールに同じタグを付けることもできます。ルールの形式と場所については、言語リファレンスを参照してください。
side: sinks の場合は、groups を順に確認します。groups[].sinks にあるすべてのメソッドに実装する rule_id があることを確認し、作成するすべてのカスタムルールに、外側の groups[].tag を付けます。side: sources の場合は、ユニットのトップレベルのタグを使用します。
3. テストの結合ルールを作成する
ライブラリルールは単独では何も出力しません。動作をテストするには、一時的なテスト結合ルールで、汎用の汚染マーカーに接続します。その側の結合ルールを1つ、テストプロジェクトのマーカールールに記述します。一方の端では汎用マーカーを参照し、もう一方ではユニットに選択した各ライブラリの 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 のままにして、「出力」に従って報告します。やみくもに編集しないでください。
出力
成果物
.opentaint/rules配下のカスタムライブラリルールファイル.opentaint/tracking/rules/<side>/<unit>.yaml— ユニットのエントリを更新したもの(トラッキングに従う)
サマリー
- 実装するライブラリルール ID(組み込みのものと作成したものを特定)、その側のテスト結果を1行でまとめたもの、および使用した正確な
test rule runコマンド - ステップ 5 で行き詰まった場合:
stages.tests_passingを pending のままにし、原因を報告します。- 失敗サンプルのフローでライブラリメソッドが脱落した場合 → 再ディスパッチの前に近似モデルを作成する必要があるメソッド
- 脱落がなく、明確なルール上の原因もない場合 → 非収束。オーケストレーターによる介入が必要です
追跡
このスキルは、各ユニットのエントリーに実装する rule_id と、そのユニットの stages.tests_passing を記録します。rule_id は、そのエントリー用に作成したカスタム lib ルール、または対象をカバーできることが確認された既存の組み込み lib ルールを示す <relative-yaml-path>#<id> 形式のロケーターです。ソースユニットのトップレベルの tag と、すべてのシンクの groups[].tag はそのまま保持してください。これらのタグは作成時の契約です。ブロックされたユニットは tests_passing: pending のままにします。
.opentaint/tracking/rules/sources/<package-kebab>.yaml — 1 パッケージにつきソースユニットを 1 つ作成します(依存関係が複数のパッケージにまたがる場合もあります)。ファイル名はそのパッケージ名の . を - に置き換えたものにします。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 — 1 パッケージにつきシンクユニットを 1 つ作成します(依存関係が複数のパッケージにまたがる場合は、それぞれを個別のユニットにします)。ファイル名はそのパッケージ名の . を - に置き換えたものにします。dependencies にはそのパッケージの由来となる依存関係を記載します。groups は、パッケージの危険な操作を再利用可能なシンクタグごとに分類します。各グループは { tag, sinks }、各シンクは { method, signature, note, rule_id } 形式です。タグはグループに属し、個々のメソッドには属しません。1 つのルールで複数のメソッドをカバーでき、複数のルールで同じ脆弱性の種類を拡張できます。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節のメタ変数名を一致させる必要があります。すべての lib ソース/シンクルールで、汚染された値を$UNTRUSTEDにバインドしてください - テスト結合の
ruleパスはルールセットルートからの相対パスです。マーカールールはテストプロジェクトのルール配下、lib ルールは組み込みまたはカスタムのスキャン対象ルールツリー配下で解決されます - ルール ID はグローバルに一意でなければなりません
- カスタム lib ルールはスキャン対象ルールツリーに配置し、テスト結合はテストプロジェクトのマーカールールにのみ配置してください
- メインプロジェクトのモデルをスキャンしないでください
- テストプロジェクトを編集しないでください
注意事項
- テストプロジェクトに誤りがあると思われる場合は、上流に差し戻してください
- ライブラリのメソッドが汚染を失わせるために合格しない陽性結果は、ルールの不具合ではありません。ルールを無理に広げて対処せず、近似対象として報告してください(ステップ 5 に従ってください)
- 生成するルールファイルにはコメントを含めないでください