create-test-project について
create-test-projectは、汚染ルールやデータフロー近似をテストするOpenTaintスキルです。指定されたメソッドと依存関係から最小限のテストプロジェクトを作成・コンパイルし、サンプルごとの期待結果を記録します。
主な機能
- 01検証タイプに応じたテストプロジェクトの作成
- 02指定メソッドのサンプル作成
- 03rule-test.yamlへの期待結果の記録
- 04サンプルをテストモデルにコンパイル
- 05メソッド単位のテスト状況を追跡
活用シーン
- 01サンプルコードでsourceまたはsinkルールをテスト
- 02データフロー近似メソッドを検証
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ seqra/ opentaint --skill create-test-projectインストール後、Claude Code で/create-test-projectを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/java-approximation.mdjava-rule.mdjava-spring-multimodule.md詳細
スキル:テストプロジェクトの作成
ルールまたは近似が検証されるフローを再現するサンプルを含む、最小限のコンパイル可能なテストプロジェクトを構築します。サンプルでは、実際のライブラリメソッドと、スキャフォールドが提供する汎用 taint マーカーとの間でデータを受け渡し、必ず生成すべき判定結果を示します。つまり、検出すべき陽性ケースと、検出してはならない陰性ケースです。成果物はコンパイル済みモデルです。サンプルのソースはモデルと一緒に配置します。
入力
呼び出し元から提供されます。省略された場合はデフォルト値を使用します。必須の入力が不足しており、妥当なデフォルト値もない場合に限り、確認してください。
project-root(任意)— 対象プロジェクトのルート。Opentaint はすべての分析成果物を固定の<project-root>/.opentaint/ディレクトリに保存するため、以下の.opentaint/...パスはすべてこの場所を基準に解決されます。デフォルト:現在のディレクトリlanguage(必須)— このプロジェクトの対象言語と言語固有の指示type(必須)— このプロジェクトで検証する内容。サンプルのスタイルと、以下の識別入力を選択します:rule-source、rule-sink、またはdataflowrule-source/rule-sinkの場合 —unit:ユニット ID。メンバーとdependenciesは.opentaint/tracking/rules/sources|sinks/<unit>.yamlから取得しますdataflowの場合 —batch:データフローメソッドとそのdependenciesを定義する.opentaint/tracking/approximations/<batch>.yamlを持つバッチ
プロジェクトフォルダー <name> には識別子を使用します。ルール側では unit、データフロー近似では batch です。
ワークフロー
1. プロジェクトをスキャフォールドする
スキャフォールドのコマンドとサンプル形式は言語固有です。type に対応するリファレンスを読みます。rule-source / rule-sink では references/<lang>-rule.md、dataflow では references/<lang>-approximation.md を参照します(自己完結したリファレンスが1つあればよく、もう一方を読む必要はありません)。type に対応するプロジェクトをスキャフォールドし、ユニットの各 dependencies を指定バージョンで渡します。スキャフォールドは汎用 taint マーカーと、サンプルが実行する固定のテストルールを提供するため、作成するのはサンプルだけです。<name> プロジェクトがすでに存在する場合(対象範囲が広がった、または依存関係が更新されたために再実行する場合)は、新しくスキャフォールドするのではなく、足りないサンプルを追加して再コンパイルします。init コマンドは該当するリファレンスに記載されています。
2. サンプルを作成する
ユニットまたはバッチの各エントリーには signature が記録されています。その呼び出し可能オブジェクトがプロジェクトで実際にどのように使用されているかに基づき、忠実なサンプルを作成します。アプリの実際のパスは関係ありません。境界とマーカーの間でデータが流れることだけが重要です。
シンクユニットの場合、メソッドは groups[].sinks の下にネストされています。後でルールを作成する人がグループ境界を維持できるようにしながら、すべてのメソッドをテストします。
- 対応するものは常に汎用マーカーとし、実際の source/sink は使用しません。これにより、サンプルではテスト対象のユニットだけを検証します
- 各サンプルは、テストの
rule-test.yamlで、生成すべき単一の判定結果に対応づけます。つまり、検出すべき陽性ケースと、タイプに応じて必要な場合は検出してはならない陰性ケースです
サンプルコード、rule-test.yaml の形式、タイプごとに必要な判定結果は、該当するリファレンスに記載されています。
3. モデルにコンパイルする
作成したプロジェクトを .opentaint/test-compiled/<name> にコンパイルします。ルール側では、スキャフォールドした単一のサブプロジェクト(sources/ または sinks/)を対応するサブモデルにコンパイルします。データフロープロジェクトは1回コンパイルします。
# rule side — the one you built
opentaint compile .opentaint/test-projects/<name>/sources -o .opentaint/test-compiled/<name>/sources
# dataflow
opentaint compile .opentaint/test-projects/<name> -o .opentaint/test-compiled/<name>
コンパイルが正常に完了した状態が成果物です。フィードバックループ:ビルド失敗は、サンプルまたは依存関係の問題として修正できます。実際のエラーを提示し、修正してから再コンパイルします。正常にコンパイルできたら、Tracking に従ってテストプロジェクトのステージを完了にします。
4. エスカレーションする
明確な原因がないまま、約3回修正してもプロジェクトをコンパイルできない場合は、失敗を報告し、オーケストレーターが対応できるようテストプロジェクトのステージを保留のままにします。
出力
実施内容を簡潔に報告します。
成果物
.opentaint/test-compiled/<name>— 後続ステージで実行するコンパイル済みテストモデルです。各パスと、使用した正確なcompileコマンドを報告してください.opentaint/test-projects/<name>— サンプルソースと、その判定結果を記録するrule-test.yamlをモデルとともに格納します
概要
- ケースごとに作成したサンプルの数
- サンプルを作成できず除外したメソッド(
failedとして記録)の一覧と、簡単な理由 - 失敗したプロジェクト(ある場合)
追跡
このスキルで書き戻すのは、テストプロジェクトのステージだけです。
- ルール側 → ソースまたはシンクのユニットで
stages.test_project: done - データフロー近似 → バッチファイルのメソッドごとに
build.test_projectエントリーを1つ追加し、サンプルがプロジェクトに含まれたメソッドはstatus: done、サンプルを作成できず除外したメソッドはstatus: failed
.opentaint/tracking/rules/sources/<package-kebab>.yaml — パッケージごとに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つのシンクユニットです(依存関係が複数のパッケージにまたがる場合、それぞれが独自のユニットになります)。ファイル名はそのパッケージ名とし、. を - に置き換えます。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
.opentaint/tracking/approximations/<batch>.yaml — 1つのバッチの呼び出し可能要素の分類です。<batch> は計画ファイルのファイル名(拡張子を除いたもの)です。各呼び出し可能要素は、計画で指定された言語固有の method と signature をキーにして、判定バケットのいずれか1つにだけ属します。これにより、異なるバリアントが別々に保たれます。
passthrough、dataflow— モデル化されたキャリアです。各エントリーは{ method, signature }ですskipped— 終端の非キャリアです。各エントリーは{ method, signature, reason }ですengine_issues— エンジンが伝播できないことを確実に証明できるキャリア用の独立したバケットです(構築されても、引き続き破棄されます)。終端として扱われ、skippedと同様に処理されます。違いは理由だけです。merge-skippedはこの項目をskipped.yamlに、通常のスキップ対象であるmethodsと並ぶ独自のengine_issuesグループとして引き継ぎます
dependencies には、データフローテストプロジェクトが必要とする依存関係の識別子を列挙します。build ブロックはビルドを追跡します。test_project には各データフローメソッドのテストプロジェクトのステータスを記録します(サンプルがバッチのテストプロジェクトに書き込まれた場合は done、サンプルを作成できずメソッドを除外した場合は failed)。done には完了した { method, signature } を記録します。コメントで明確にしてください
passthrough:
- { method: "<qualified-member-a>", signature: "<language-signature-a>" }
dataflow:
- { method: "<qualified-member-b>", signature: "<language-signature-b>" }
skipped:
- { method: "<qualified-member-c>", signature: "<language-signature-c>", reason: "retains none of its input data" }
engine_issues: []
dependencies: []
build:
test_project:
- { method: "<qualified-member-b>", signature: "<language-signature-b>", status: done }
done: []
制約
OpenTaint は、プログラム全体を対象とする、インタープロシージャルかつフィールドセンシティブなエイリアス解析エンジンです。表示可能なアプリケーションコード、呼び出し、エイリアス、個々のフィールドをすでに伝播対象としています。カスタムルールと近似は、割り当てられたソース、シンク、または不透明なメソッドの境界だけをモデル化します。コンパイル時定数とリテラルはテイントを持たないため、出力が定数だけのソースやキャリアは何も導入しません。
- ユニットごとに
<name>フォルダーを1つ用意します。他のユニットのテストプロジェクトには決して書き込まないでください。これにより、並行して作業するエージェント同士の競合を防ぎます