variant-analysis について
許可を得た防御的セキュリティ調査向けの脆弱性バリアント分析ガイドです。既知の脆弱性からパターンを導き、CodeQL や Semgrep で類似問題を探します。
主な機能
- 01脆弱性シードのパターン分析
- 02CodeQL データフロークエリ作成
- 03Semgrep マッチルール作成
- 04リポジトリ横断の変種検索
- 05検出結果の分類と報告
活用シーン
- 01所有コード内で既知の脆弱性を探索
- 02CVE 公開後に類似の欠陥を調査
- 03関連する複数リポジトリをレビュー
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ oimiragieo/ agent-studio --skill variant-analysisインストール後、Claude Code で/variant-analysisを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
commands/variant-analysis.mdhooks/post-execute.cjspre-execute.cjsreferences/research-requirements.mdrules/variant-analysis.mdschemas/input.schema.jsonoutput.schema.jsonscripts/main.cjstemplates/implementation-template.md詳細
バリアント分析
セキュリティに関する注意事項
許可された用途に限ります:これらのスキルは、防御的なセキュリティ分析と許可された調査に使用します。
- 書面による許可を得たセキュリティ評価
- 自らが所有するコードベースにおける予防的な脆弱性発見
- CVE 報告後のインシデント対応としてのバリアント探索
- 適切な脆弱性開示を伴うセキュリティ調査
- 管理された環境での教育目的
次の目的では絶対に使用しないでください:
- 許可なくシステムをスキャンすること
- 許可されていない用途でエクスプロイトを開発すること
- セキュリティ制御を回避すること
- あらゆる違法行為
ステップ 1:シードとなる脆弱性の分析
既知の脆弱性(CVE、バグ報告、コードパターン)を出発点とします。
脆弱性パターンの抽出
- バグクラスを特定する:どの種類の脆弱性ですか?(SQL インジェクション、XSS、バッファオーバーフロー、TOCTOU など)
- ソースを特定する:信頼できないデータはどこから入りますか?(ユーザー入力、ネットワーク、ファイル、環境)
- シンクを特定する:データはどこで問題を引き起こしますか?(SQL クエリ、HTML 出力、メモリへの書き込み、システムコール)
- 欠落しているサニタイズ処理を特定する:ソースとシンクの間で、どのようなチェックや変換が行われていませんか?
- パターンを抽象化する:個別の事例にとどまらず一般化します
シード分析の例
CVE-2024-XXXX: SQL Injection in user search
- Bug class: CWE-089 (SQL Injection)
- Source: HTTP request parameter `q`
- Sink: String concatenation into SQL query
- Missing: Parameterized query or input sanitization
- Pattern: request.param → string concat → db.query()
ステップ 2:パターンの一般化
シードをクエリパターンに変換します。
抽象化のレベル
| レベル | 説明 | 例 |
|---|---|---|
| 完全一致 | 同じ関数、同じファイル | searchUsers(req.query.q) |
| ローカル | 同じパターン、異なる関数 | 任意の db.query("..."+userInput) |
| 構造的 | 同じデータフローの形状 | サニタイズ処理のない、あらゆるソースからシンクへのデータフロー |
| 意味的 | 同じバグクラス、構文は問わない | あらゆる SQL インジェクションのバリアント |
CodeQL パターンテンプレート
/**
* @name Variant of CVE-XXXX: [description]
* @description Finds code structurally similar to [seed vulnerability]
* @kind path-problem
* @problem.severity error
* @security-severity 8.0
* @precision high
* @id js/variant-cve-xxxx
* @tags security
* external/cwe/cwe-089
*/
import javascript
import DataFlow::PathGraph
class UntrustedSource extends DataFlow::Node {
UntrustedSource() {
// Define sources: HTTP parameters, request body, etc.
this = any(Express::RequestInputAccess ria).flow()
}
}
class VulnerableSink extends DataFlow::Node {
VulnerableSink() {
// Define sinks: string concatenation in SQL context
exists(DataFlow::CallNode call |
call.getCalleeName() = "query" and
this = call.getArgument(0)
)
}
}
class VariantConfig extends DataFlow::Configuration {
VariantConfig() { this = "VariantConfig" }
override predicate isSource(DataFlow::Node source) {
source instanceof UntrustedSource
}
override predicate isSink(DataFlow::Node sink) {
sink instanceof VulnerableSink
}
override predicate isBarrier(DataFlow::Node node) {
// Known sanitizers that prevent the vulnerability
node = any(DataFlow::CallNode c |
c.getCalleeName() = ["escape", "sanitize", "parameterize"]
).getAResult()
}
}
from VariantConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
select sink.getNode(), source, sink,
"Potential variant of CVE-XXXX: untrusted data flows to SQL query without sanitization."
Semgrep パターンテンプレート
rules:
- id: variant-cve-xxxx-sql-injection
message: >
Potential variant of CVE-XXXX: User input flows into SQL query
via string concatenation without parameterization.
severity: ERROR
languages: [javascript, typescript]
metadata:
cwe:
- CWE-089
confidence: HIGH
impact: HIGH
category: security
technology:
- express
- node.js
references:
- https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-XXXX
patterns:
- pattern-either:
- pattern: |
$DB.query("..." + $USERINPUT + "...")
- pattern: |
$DB.query(`...${$USERINPUT}...`)
- pattern: |
$QUERY = "..." + $USERINPUT + "..."
...
$DB.query($QUERY)
- pattern-not:
- pattern: |
$DB.query($QUERY, [...])
fix: |
$DB.query($QUERY, [$USERINPUT])
ステップ 3:バリアントの発見
分析の実行
# CodeQL variant scan
codeql database analyze codeql-db \
--format=sarifv2.1.0 \
--output=variant-results.sarif \
./variant-queries/
# Semgrep variant scan
semgrep scan \
--config=./variant-rules/ \
--sarif --output=variant-semgrep.sarif
# Cross-repo CodeQL scan (GitHub)
codeql database analyze codeql-db-repo-1 codeql-db-repo-2 \
--format=sarifv2.1.0 \
--output=cross-repo-variants.sarif \
./variant-queries/
手動でのパターン検索
自動化ツールでバリアントを見つけられない場合は、手動で検索します。
# Search for the syntactic pattern
grep -rn "db\.query.*\+" --include="*.js" --include="*.ts" .
# Search for the function call pattern
grep -rn "\.query\s*(" --include="*.js" --include="*.ts" . | grep -v "parameterized\|escape\|sanitize"
# AST-based search with ast-grep
sg -p 'db.query("..." + $X)' --lang js
ステップ 4:バリアントの分類
各バリアントのトリアージ
発見した各事例を、次の要素に基づいて分類します。
| 要素 | 質問 | 優先度への影響 |
|---|---|---|
| 到達可能性 | 攻撃者はこのコードパスに到達できますか? | 到達可能な場合は重大 |
| 悪用可能性 | 脆弱性を悪用できますか? | 悪用可能な場合は重大 |
| 影響度 | 悪用によってどのような被害が発生しますか? | CIA トライアドに基づく |
| 確信度 | 真陽性であるとどの程度確信できますか? | 高/中/低 |
| 類似度 | 構造的にシードとどの程度近いですか? | 高いほど確信度も高い |
バリアント群の追跡
## Variant Family: CWE-089 SQL Injection
### Seed: CVE-XXXX (src/api/users.js:42)
- Pattern: request.param -> string concat -> db.query()
### Variants Found:
1. **V-001** src/api/products.js:78 (HIGH confidence)
- Same pattern, different endpoint
- Exploitable: YES
- Fix: Use parameterized query
2. **V-002** src/api/orders.js:123 (MEDIUM confidence)
- Similar pattern, additional transform
- Exploitable: NEEDS INVESTIGATION
- Fix: Use parameterized query
3. **V-003** src/legacy/search.js:45 (LOW confidence)
- Partial match, may be sanitized upstream
- Exploitable: UNLIKELY
- Fix: Verify sanitization chain
ステップ 5:修正とレポート
バリアント分析レポート
## Variant Analysis Report
**Seed**: [CVE/bug ID and description]
**Date**: YYYY-MM-DD
**Scope**: [repositories/directories analyzed]
**Tools**: CodeQL, Semgrep, manual review
### Executive Summary
- Variants found: X
- Critical: X | High: X | Medium: X | Low: X
- False positives: X
- Estimated remediation effort: X hours
### Variant Details
[For each variant: location, classification, remediation]
### Pattern Evolution
[How the pattern varies across the codebase]
### Recommendations
1. Fix all CRITICAL/HIGH variants immediately
2. Add regression tests for each variant
3. Add CI/CD checks to prevent pattern recurrence
4. Consider architectural changes to eliminate the bug class
共通の脆弱性シードパターン
インジェクションのバリアント
| シードパターン | バリアント検出クエリ |
|---|---|
| 文字列連結による SQL インジェクション | source -> string.concat -> db.query |
| 文字列補間によるコマンドインジェクション | source -> template.literal -> exec |
| innerHTML による XSS | source -> assignment -> innerHTML |
| ユーザー指定パスによるパストラバーサル | source -> path.join -> fs.read |
認証のバリアント
| シードパターン | バリアント検出クエリ |
|---|---|
| 認証チェックの欠如 | route.handler without auth.middleware |
| 弱い比較 | password == input (not timing-safe) |
| トークンの再利用 | token.generate without uniqueness |
関連スキル
static-analysis- SARIF 出力を使用した CodeQL と Semgrepsemgrep-rule-creator- カスタム脆弱性検出ルールdifferential-review- セキュリティに重点を置いた差分分析insecure-defaults- ハードコードされた認証情報とフェイルオープンの検出security-architect- STRIDE 脅威モデリング
エージェント統合
- security-architect(プライマリ):脅威モデリングと脆弱性評価
- code-reviewer(セカンダリ):パターンを考慮したコードレビュー
- penetration-tester(セカンダリ):バリアントのエクスプロイト検証
絶対原則
- パターンクエリを作成する前に、必ず確認済みのシード脆弱性から始めてください
- 既知のシード脆弱性に一致することを確認する前に、クエリの範囲を決して広げないでください
- 広範囲にスキャンする前に、少なくとも 1 つの既知の脆弱性があるインスタンスに対して、パターンクエリを必ずテストしてください
- 到達可能性と悪用可能性を手動でトリアージして確認せずに、バリアントの検出結果を決して報告しないでください
- あるコードベースでバリアントが確認された場合は、関連するすべてのリポジトリを必ず確認してください
アンチパターン
| アンチパターン | 失敗する理由 | 正しいアプローチ |
|---|---|---|
| 完全一致のクエリのみを使用 | リファクタリングされたバリアントや構文の異なるバリアントを見逃します | パターンを抽象化し、4 つすべての抽象化レベルでテストします |
| シード検証の手順がない | クエリが既知の脆弱性に一致しない可能性があります | まずシードインスタンスに対してクエリをテストします |
| 範囲が広すぎるパターン | 偽陽性率が高くなり、トリアージに時間を浪費します | 既知の安全なパターンには pattern-not を使って範囲を絞ります |
| 単一リポジトリのスキャン | 関連リポジトリにバリアントが存在する可能性があります | 同じフレームワークを使う関連リポジトリをすべてスキャンします |
| 最初のバリアントを見つけた時点で終了 | バグクラスの修正が不完全なままになります | コードベース全体を網羅的に検索します |
メモリプロトコル(必須)
開始前:
.claude/context/memory/learnings.md を読みます
完了後:
- 新しいパターン ->
.claude/context/memory/learnings.md - 発見した問題 ->
.claude/context/memory/issues.md - 決定事項 ->
.claude/context/memory/decisions.md
中断されることを前提にしてください。メモリに記録されていなければ、実行されていないのと同じです。
コメント
Markdown 対応