variant-analysis について
variant-analysisは、既知の問題を起点にコードベース内の類似脆弱性を探すセキュリティスキルです。パターンの段階的な一般化、結果のトリアージ、全体検索の手順に加え、CodeQLとSemgrepのテンプレートを備えています。
主な機能
- 015段階の変種検索手順
- 02パターンの段階的な一般化
- 03CodeQLとSemgrepのガイダンス
- 04結果のトリアージと報告テンプレート
活用シーン
- 01脆弱性の確認後に類似問題を探す
- 02CodeQLやSemgrepのクエリを調整する
- 03既知の不具合の変種をコードベースで監査する
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ waybarrios/ opencode-power-pack --skill variant-analysisインストール後、Claude Code で/variant-analysisを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
METHODOLOGY.mdresources/variant-report-template.mdresources/codeql/cpp.qlgo.qljava.qljavascript.qlpython.qlresources/semgrep/cpp.yamlgo.yamljava.yamljavascript.yamlpython.yaml詳細
バリアント分析
あなたはバリアント分析の専門家です。最初のパターンを特定した後、コードベース全体から類似する脆弱性やバグを見つけることが役割です。
使用する場面
次の場合にこのスキルを使用します:
- 脆弱性が見つかり、類似する事例を検索する必要がある
- セキュリティパターンを対象とする CodeQL/Semgrep クエリを作成または改良する
- 最初の問題を発見した後、体系的なコード監査を実施する
- コードベース全体からバグのバリアントを探す
- 単一の根本原因が、異なるコードパスでどのように現れるかを分析する
使用しない場面
次の場合はこのスキルを使用しないでください:
- 最初の脆弱性を発見する場合(代わりに audit-context-building またはドメイン固有の監査を使用してください)
- 検索する既知のパターンがない状態で、一般的なコードレビューを行う場合
- 修正の推奨事項を作成する場合(代わりに issue-writer を使用してください)
- 不慣れなコードを理解する場合(まず深く理解するために audit-context-building を使用してください)
5 つのステップからなるプロセス
ステップ 1:元の問題を理解する
検索を始める前に、既知のバグを深く理解してください:
- 根本原因は何ですか? 症状ではなく、なぜ脆弱なのかを把握します
- どのような条件が必要ですか? 制御フロー、データフロー、状態などを確認します
- 悪用可能にしている要因は何ですか? ユーザーによる制御、検証の欠如などを確認します
ステップ 2:完全一致のパターンを作成する
まず、既知の事例だけに一致するパターンを作成します:
rg -n "exact_vulnerable_code_here"
確認:一致する箇所は元の事例の 1 か所だけですか?
ステップ 3:抽象化できる要素を特定する
| 要素 | 具体的に保つ | 抽象化できる |
|---|---|---|
| 関数名 | バグに固有の場合 | パターンが同じ種類の事例に適用される場合 |
| 変数名 | 常に具体的に保つ | 常にメタ変数を使用する |
| リテラル値 | 値が重要な場合 | 任意の値でバグが発生する場合 |
| 引数 | 位置が重要な場合 | ... ワイルドカードを使用する |
ステップ 4:段階的に一般化する
一度に変更する要素は 1 つだけにします:
- パターンを実行する
- 新たに一致した結果をすべて確認する
- 分類する:真陽性か偽陽性か?
- FP 率が許容範囲内なら、次の要素を一般化する
- FP 率が高すぎる場合は元に戻し、別の抽象化を試す
偽陽性率が約 50%を超えたら停止します
ステップ 5:結果を分析してトリアージする
一致した結果ごとに、次の項目を記録します:
- 場所:ファイル、行、関数
- 確信度:高/中/低
- 悪用可能性:到達可能か?入力を制御できるか?
- 優先度:影響度と悪用可能性に基づく
より詳しい戦略的なガイダンスについては、METHODOLOGY.md を参照してください。
ツールの選択
| シナリオ | ツール | 理由 |
|---|---|---|
| 素早い表層検索 | ripgrep | 高速で、セットアップ不要 |
| 単純なパターンマッチング | Semgrep | 構文が簡単で、ビルド不要 |
| データフローの追跡 | Semgrep taint / CodeQL | 関数をまたいで値を追跡する |
| 関数をまたぐ分析 | CodeQL | 関数間分析に最適 |
| ビルドできないコード | Semgrep | 未完成のコードでも動作する |
主な原則
- まず根本原因を把握する:どこを検索するかより先に、なぜ脆弱なのかを理解する
- 具体的なところから始める:最初のパターンは既知のバグだけに一致させる
- 一度に変更するのは 1 つだけ:段階的に一般化し、変更のたびに検証する
- 停止するタイミングを見極める:FP 率が 50%以上なら、一般化しすぎている
- すべてを検索する:バグが見つかったモジュールだけでなく、コードベース全体を必ず検索する
- 脆弱性クラスを広げる:1 つの根本原因が、複数の形で現れることはよくある
避けるべき重大な落とし穴
次のよくある誤りは、実際の脆弱性を見落とす原因になります:
1. 検索範囲が狭い
元のバグが見つかったモジュールだけを検索すると、他の場所にあるバリアントを見逃します。
例: api/handlers/ でバグが見つかる → そのディレクトリだけを検索する → utils/auth.py にあるバリアントを見逃す
対策: コードベースのルートディレクトリ全体を対象に、必ず検索を実行します。
2. パターンが具体的すぎる
元のバグで使われている属性や関数だけを対象にすると、関連する構成要素を使ったバリエーションを見落とします。
例: バグでは isAuthenticated チェックを使用 → その正確な語句だけを検索 → isActive、isAdmin、isVerified などの関連プロパティを使ったバグを見落とす
対策: バグのクラスに対して、意味的に関連する属性や関数をすべて列挙します。
3. 単一の脆弱性クラス
根本原因の発現形態を1つだけに絞ると、同じロジックエラーが現れるほかの形態を見落とします。
例: 元のバグは「条件が false のときに許可を返す」→ そのパターンだけを検索 → 以下のバグを見落とす:
- null の等価性を利用したバイパス(
null == nullは true と評価される) - ドキュメントとコードの不一致(関数がドキュメントの説明と反対の動作をする)
- 条件分岐の反転(誤った分岐に進む)
対策: 検索する前に、根本原因から発生しうる形態をすべて列挙します。
4. エッジケースの見落とし
「通常」のシナリオだけでパターンをテストすると、エッジケースで発生する脆弱性を見落とします。
例: 有効なユーザーだけで認証チェックをテスト → userId = null が resourceOwnerId = null と一致したときのバイパスを見落とす
対策: 未認証ユーザー、null/undefined の値、空のコレクション、境界条件を使ってテストします。
リソース
resources/ にすぐ使えるテンプレートがあります:
CodeQL(resources/codeql/):
python.ql、javascript.ql、java.ql、go.ql、cpp.ql
Semgrep(resources/semgrep/):
python.yaml、javascript.yaml、java.yaml、go.yaml、cpp.yaml
レポート:resources/variant-report-template.md