trailmark-finding-triage について
Trailmark のグラフ証拠を使い、候補となるコード上の問題を1件ずつトリアージするセキュリティレビュー用スキルです。到達可能性や影響を評価し、手動確認が必要な点も整理します。
主な機能
- 01指摘内容の正規化
- 02指摘とグラフノードの対応付け
- 03エントリーポイントからの到達性分析
- 04汚染と信頼境界の調査
- 05判定と証拠パケットの作成
活用シーン
- 01静的解析結果のトリアージ
- 02関数がエントリーポイントから到達可能か確認
- 03PoC 作成前の証拠整理
- 04疑わしいコード指摘の優先順位付け
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ trailofbits/ skills --skill trailmark-finding-triageインストール後、Claude Code で/trailmark-finding-triageを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
agents/openai.yamlassets/trail-of-bits-mark.svgreferences/input-normalization.mdoutput-format.mdquery-recipes.mdscripts/evidence_packet.pytest_evidence_packet.py詳細
Trailmark Finding Triage
候補となる指摘 1 件について、簡潔なグラフ証拠パケットを作成します。このスキルでは、影響を受けるコードに到達可能か、どのグラフ証拠が主張を裏付ける、または弱めるのか、そして問題を悪用可能と判断する前にどのような手動レビューが必要かを確認します。
使用する場合
- PoC に時間をかける前に、静的解析の結果 1 件をトリアージする
- 手動で見つけた指摘がエントリーポイントから到達可能か確認する
- PoC 作業用の証拠パケットを作成する
- 手動監査で見つかった不審な関数 1 件をレビューする
- 問題 1 件を昇格させるか、優先度を下げるか、より広範なチェーン分析の一部として扱うか判断する
使用しない場合
- 複数の確度の低い指摘が組み合わさることで、より強力なチェーンになる可能性があります。代わりにチェーンまたは構成ワークフローを使用してください。
- ユーザーが完全な監査を求めています。代わりに監査または設計レビューのワークフローを使用してください。
- ユーザーが既知の指摘の修正検証を求めています。代わりに修正レビューのワークフローを使用してください。
- 対象が PR またはブランチ差分です。
graph-evolutionと差分レビューのワークフローを使用してください。 - 具体的な指摘、関数、ファイル/行、または不審なシンクがまだありません。まず検出スキルを使用してください。
却下すべき合理化
| 合理化 | 誤りである理由 | 必須の対応 |
|---|---|---|
| 「スキャナーが重大度高と判定しているので、到達可能性は明らかです」 | 静的解析の指摘を昇格させる前に、グラフとコードのコンテキストが必要です | 指摘をグラフノードに紐付け、エントリーポイントからのパスを確認する |
| 「エントリーポイントからのパスがないので、不可能です」 | パーサー、プロキシ、または動的ディスパッチの制限が原因の可能性があります | 到達可能性とは分けて制限を報告する |
| 「パス上に認証チェックがあるので、この問題は安全です」 | チェックが誤った条件を検証していたり、別のパスから回避できたりする可能性があります | 検証/認証を証明ではなくレビュー対象として扱う |
| 「到達可能なパスが 1 つあれば、PoC の主張には十分です」 | そのパスには、攻撃者が制御する入力と、条件の適合性も必要です | グラフ上の到達可能性と悪用可能性を分ける |
| 「これはおそらくチェーンです」 | 単一指摘のトリアージでは、候補 1 件のみを扱います | 関連する指摘を構成ワークフローに引き継ぐ |
ワークフロー
Finding Triage Progress:
- [ ] Step 1: Normalize the candidate
- [ ] Step 2: Build or reuse the Trailmark graph
- [ ] Step 3: Bind the candidate to graph node(s)
- [ ] Step 4: Analyze reachability, taint, boundaries, and blast radius
- [ ] Step 5: Decide and emit the evidence packet
ステップ 1:候補を正規化する
ファイル/行、関数名、SARIF 結果、weAudit アノテーション、Markdown の指摘抜粋、または手動での主張を受け付けます。次の項目に正規化してください。
- タイトル
- ソースの種類
- ファイルパスと行範囲(ある場合)
- 関数またはノードのヒント
- 疑わしいソース、シンク、またはアセット
- 主張されている影響
具体的なコード上の位置を特定できない場合は、ここで停止して提示を求めてください。
入力処理の詳細については、 references/input-normalization.md を参照してください。
ステップ 2~4 のショートカット(ファイル/行での指摘事項)
ファイル/行アンカーには、同梱スクリプトを実行します。グラフと事前解析を一度だけ構築し、すべての指摘事項をバインドして、Graph Evidence のフィールドを JSON として出力します。すべての一致ノードと主要ノード(最初の行を含むノード、その次に最も範囲の狭いノード)、各エントリーポイントの信頼レベルを含むエントリーポイントへのパス、tainted /
entrypoint_reachable / privilege_boundary / high_blast_radius への所属、呼び出し元、呼び出し先、下流ノード、および Trailmark のバージョンが出力されます。指摘事項ごとにグラフを再構築するのではなく、複数の指摘事項をまとめて渡します。
uv run --no-project "{baseDir}/scripts/evidence_packet.py" --target <dir> --finding <file>:<line>[-<end>] --out evidence.json [--finding ...] [--language auto]
--out を指定すると、完全なパケットはディスクに保存され、標準出力には処理件数のみが出力されます。そのファイルから関連する指摘レコードを読み取ります。--out を指定しない場合、標準出力には完全なパケットが出力されます。相対アンカーは、対象ディレクトリ基準または作業ディレクトリ基準として扱われる場合があります。既存のパスが曖昧な場合は拒否されます。--path-base target または cwd を選択するか、絶対パスを使用してください。行番号は正の値で、順序どおりである必要があります。列の構文には対応していません。呼び出し可能な要素と重複しない場合、コンテナはモジュール/クラス/コントラクトの宣言を対象とします。結果を評価する前に、binding(exact、nested、ambiguous)、binding_kind、すべての一致、利用できないシグナル、パーサー診断の制限を確認してください。ノード数がゼロのグラフは失敗です。
バッチ処理で共有されるのはグラフ処理のみです。各指摘事項について個別の人間による判定を記述してください。
何にもバインドされない指摘事項は、bound_node: null とその理由を返します。スクリプトは何も判定しません。バインドされたコードとその呼び出し元を読み、攻撃者による制御が可能かを判断してください。また、パスの一覧が空の場合は、証明としてではなく、説明すべき制限(動的ディスパッチ、プロキシ、エントリーポイントモデルの不足)として扱ってください。スクリプトが受け付けない入力(関数名、audit-augmentation 経由の SARIF)や、実行しないクエリ(connect_subgraphs)には、以下の手順を使用してください。
ステップ 2:グラフを構築する、または再利用する
公開されている trailmark スキルのワークフローを使用します。既存の新しいエクスポート済みグラフまたは .trailmark/ アーティファクトがあれば、そちらを優先します。それ以外の場合は、language="auto" または対象の明示的な言語リストでグラフを構築し、続いて engine.preanalysis() を実行します。
使用した Trailmark のバージョンまたは機能プローブを記録してください。Trailmark 0.4 専用の API は、hasattr() または CLI のヘルプ確認によって機能の有無を判定してください。
ステップ 3:候補をバインドする
まずファイルと行の重複でバインドし、次に関数名とファイルでバインドします。複数のノードが一致する場合は、候補をすべて列挙し、包含範囲が最も狭いノードを主要ノードとして選択します。一致するノードがない場合は、推測せずにバインド上の制限を報告してください。
SARIF および weAudit のユーザーは、一致する要素の特定に audit-augmentation ワークフローを再利用し、その後、注釈付きノードを確認してください。
ステップ 4:グラフの証拠を分析する
references/query-recipes.md のクエリ手順を実行します。
- バインドされたノードへのエントリーポイントパス
- 利用可能な場合は、各パスの信頼レベル
tainted、privilege_boundary、high_blast_radiusのサブグラフへの所属- 直接の呼び出し元と呼び出し先
- 影響度の高い下流のシンク
- 手動レビューに値する兄弟ノードまたは近接ノード
グラフ上の到達可能性を、悪用可能性の証明として扱わないでください。
ステップ 5:判定して引き継ぐ
次のいずれかの判定を出します。
| 判定 | 意味 |
|---|---|
Promote | グラフの証拠が到達可能性と妥当な影響を裏付けています |
Needs manual review | 証拠は示唆的ですが、決定的ではありません |
Deprioritize | 到達可能なパスがないか、信頼されたパス/内部パスのみが見つかりました |
Blocked | バインドまたは Trailmark の分析に失敗しました |
references/output-format.md に従って、証拠パケットを記述します。
昇格対象となった PoC 作成に値する問題は、ユーザーの PoC ワークフローに引き継ぎます。関連する指摘事項は、組み合わせ分析のワークフローに引き継ぎます。再現可能な根本原因は、trailmark-variant-neighborhood、variant-analysis、またはカスタム Semgrep/CodeQL ルールのワークフローに引き継ぎます。
プロンプトの例
- 「
src/Vault.sol:148で Trailmark の検出結果のトリアージを行ってください。withdraw で残高の更新を回避できると思います。」 - 「PoC に時間をかける前に、この SARIF の検出結果をトリアージしてください。
contracts/Bridge.solの 91 行目にあるsemgrep:error unchecked-transferです。」 - 「このレポートの抜粋では、
parse_packetに攻撃者が到達できると主張しています。Trailmark のエビデンスパケットを作成し、まだ不足しているものを教えてください。」