verifying-skill-accuracy について
LLM の支援で作成された技術スキルを一次資料と照合するための検証技能です。情報源の優先順位と再現可能な確認方法を示し、セキュリティ分析を気づかれないまま歪める誤りを重視します。
主な機能
- 01一次資料に基づく主張の検証
- 02体系的な誤りの優先確認
- 03ドキュメントと識別子の照合
- 04切り詰められた結果からの断定回避
- 05見逃されやすい誤りの重点確認
活用シーン
- 01既存の SKILL.md の監査
- 02新規または改訂した技術内容の検証
- 03報告されたコマンドや識別子の問題確認
- 04検証スタンプ付与前の内容確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ trilwu/ secskills --skill verifying-skill-accuracyインストール後、Claude Code で/verifying-skill-accuracyを入力して読み込まれたか確認します。
詳細
スキルの正確性を検証する
このリポジトリのスキルは、LLM の支援を受けて作成されています。方法論は通常妥当ですが、具体的な内容は確認するまで信頼できません。初回の検証で測定された誤り率は、12 個中 11 個のスキルに事実誤認が 31 件あり、スキルあたり約 2.6 件でした。両方の検証で誤りがなかったスキルは 1 個だけです。検証済みの印がないものには、この誤り率が当てはまると考えてください。
このスキルでは、その誤り率を下げ、スキルを検証済みと言ってよい条件を判断するための手順を説明します。
使用する場面
- 既存の SKILL.md を一次情報と照合して監査するとき
verified:のフロントマターの印を追加または更新する前- 新しいスキルの内容を作成した後、書いた具体的な内容を確認するとき
- 読者から、コマンド、ID、またはフィールド名が機能しないと報告されたとき
- 作成者がモデルである技術的な内容をレビューするとき
使用しない場面
- スキルをゼロから新規作成するとき —
authoring-security-skillsを使い、その後、最後の確認としてこのスキルで検証してください - 構造やスタイルの問題(フロントマター、セクション、行数) — それには
python3 scripts/validate.py --strictを使います。これは形式のみをチェックします - ある手法がよい考えかどうかを判断するとき — それは事実ではなく、判断の問題です
核心となる区別:形式と真偽
このリポジトリの CI は閉じたループです。validate.py、sync_attack.py、run_evals.py は、フロントマターの形式、相互参照の整合性、ATT&CK インデックスの一貫性、および自ら作成した評価ケースに対する振り分けをチェックします。スキルに記載されたコマンドが存在しなくても、これらはすべて合格する可能性があります。
CI が成功すれば、スキルの形式が正しいことを意味します。内容が真実かどうかについては何も示しません。テストの実行に合格したことを、正確性の根拠として決して引用しないでください。
コレクション全体を対象に、種類ごとに一括確認する
誤りの種類を特定したら、次に進む前に該当する箇所をすべて確認してください。誤りが見つかったスキルだけに限定してはいけません。特定の種類の誤りは複数のスキルに集中するため、スキルごとに確認するだけではコレクション内の不整合が残ります。
このリポジトリの 2 つの例が、その理由を示しています。古い Sigma 日付形式は writing-sigma-rules で修正されましたが、その後、すでに検証済みの印が付いていたスキル engineering-detections でも再び見つかりました。スキルごとの確認では、別の場所で修正された種類の誤りが対象に含まれていなかったためです。また、investigating-m365-entra では最新の Graph 相当のコマンドレットが使われていた一方で、attacking-entra-id では廃止された AzureAD PowerShell コマンドレットがまだ使われていました。コレクション内で記述が矛盾しており、横断的に grep して初めて判明しました。
つまり、ある箇所を修正したら、すぐにすべてのスキルを対象にそのパターンを grep し、どの種類を一括確認したかをコミットに記載してください。セキュリティ関連のコレクションで一括確認する価値のある種類には、ツール名の変更やアーカイブされたプロジェクト、CVE ID、クラウドのメタデータエンドポイント、削除された API バージョン、デフォルトのポート、仕様のバージョンに関する記述、プラットフォームのバージョンに依存する動作などがあります。
トリアージ:個別の誤りより、種類ごとの誤りを先に確認する
事実を一つずつ確認することから始めないでください。まず、その前提が崩れると、以下の内容すべてが無効になるような体系的な主張がないかを考えてください。
analyzing-memory-images では、スキルが Volatility を volatility3 として実行していました。実際のエントリーポイントは vol です。この 1 件の誤りによって、ファイル内の40 個すべてのコマンドがコピーして使えない状態になっていました。後から見つかった、存在しない 2 つのプラグインによる影響よりはるかに大きく、置き換え 1 回で修正できる誤りでした。
次の順で確認してください。
- ツールの識別 — バイナリやエントリーポイントの名前、および構文が対応するメジャーバージョン。Volatility 2 と 3 では、共通するコマンド体系はほとんどありません。
- 命名規則 — ツールがプラグイン、モジュール、サブコマンドにどのような名前を付けるか。この規則を正しく把握すれば、数十行にわたる記述をまとめて検証、または無効と判断できます。
- パスとファイルの規則 — 対象バージョンで成果物が実際にどこに保存されるか。
- 個々の主張 — ここで初めて、一つずつ確認します。
種類ごとの誤りは修正コストが低く、見逃した場合のコストは高くなります。個別の誤りはその逆です。
情報源の優先順位
利用可能な最上位の情報源を使い、使用したティアを記録してください。
| ティア | 情報源 | 用途 |
|---|---|---|
| 1 | 特定のバージョンの公式ドキュメント、上流ソース、RFC、ベンダー独自のリファレンス | コマンド構文、プラグイン名、API の形状、プロトコルの詳細 |
| 2 | ベンダーの KB、リリースノート、変更履歴、変更を告知する公式ブログ | デフォルト設定、保持期間、ライセンス要件、非推奨化 |
| 3 | メンテナーが執筆した記事、ツールの作者によるカンファレンス資料 | 意図、注意点、動作の理由 |
| 4 | コミュニティの投稿、チュートリアル、Stack Overflow | ティア 1 で検証するための手がかり — 引用元としては決して使わないでください |
| — | モデルの記憶 | 何にも使いません。主張には一切使いません。 |
表に加えて、次の 2 つのルールがあります。
- バージョンを一致させてください。 2.x のドキュメントでは 3.x の動作を裏付けられません。
latestまたはstableのドキュメントブランチを優先し、スキルが古い固定バージョンを対象としている場合はその旨を記してください。 - 単に真実かどうかだけでなく、最後に変更された時期を確認してください。 ベンダーのデフォルト設定は変わります。Microsoft の Audit(Standard)の保持期間は、2023 年 10 月に 90 日から 180 日へ変更されました。それ以前に書かれた資料は、一見して誤りと分からないまま、現在では間違っている可能性があります。
記憶だけを根拠に、次の内容を断定しないでください
これらはいずれも、このリポジトリで実際に誤りを生んでいます。
- CLI のエントリーポイントとサブコマンド名
- プラグイン、モジュール、パッケージの名前
- バージョン番号、および「デフォルトは X」という主張
- イベント ID とその正確な意味(4778 はセッションの再接続であり、接続ではありません)
- ログのフィールド名と列名
- 保持期間とライセンス要件
- CVE ID、CVSS ベクトル、影響を受けるバージョンの範囲
- API パス、パラメーター名、必須スコープ
- 判例と裁判の結果 — このリポジトリのある草稿では、Mango Markets と Platypus を、有罪判決によって搾取が窃盗として処罰されることを証明する事例として引用していました。どちらも実際の結果とは逆でした。Platypus の 2 人はパリで無罪となり、Eisenberg に対する Mango の有罪判決は 2025 年 5 月に取り消されました。記憶に頼った結果、確信に満ちた誤った主張が生まれました。
情報源の読み方:HTML ではなく Markdown を取得する
ドキュメントは、ページを主要なコンテンツに絞り込み、YAML フロントマター付きの Markdown を返す defuddle.md を通じて取得してください。URL の先頭に付けます。
curl -sL "https://defuddle.md/learn.microsoft.com/en-us/purview/audit-log-retention-policies"
パスではスキームを省略できます。defuddle.md/example.com/x と defuddle.md/https://example.com/x のどちらも機能します。
理由は 2 つあります。重要度は後者のほうが高いです。
- トークン数を削減できます。 このリポジトリの調査で使用したページとの比較では、散文中心のドキュメントページ(Microsoft Learn)で 78%、リンクの多い API インデックスで 33% 小さくなりました。散文は大幅に短くなりますが、リンクの表はそれほど短くなりません。
- ページ全体のテキストを、決定的な形で返します。 モデルによるページの要約ではなく、
grepできる Markdown としてページ全体を取得できます。これにより、以下で説明するような否定的な結論を安全に導けます。
ドキュメント、仕様書、ベンダーの KB、記事には使用してください。次のものには使用しないでください。
- JSON または API レスポンス — 読みやすさを高めるための抽出処理で、構造化データが壊れます。生データを直接取得してください。
- HTTP ステータスの確認 — 必要なのは実際のホストのステータスであり、独自のエラーページに 200 を返す可能性があるプロキシのステータスではありません。
- 内部、クライアント所有、または対象所有のもの。 URL はあなたのマシンを離れ、第三者に送られます。エンゲージメントの URL、内部ホスト名、クライアントの環境を、外部の抽出サービスに決して送らないでください。対象は公開されているベンダーのドキュメントに限ります。
- 認証が必要なページ、または JavaScript で描画されるページ — 匿名クライアントとして取得されます。
取得がブロックされても、否定的な結果を意味するわけではありません。 ホストによっては抽出ツールを拒否し、ページの代わりにエラーの本文を返します。たとえば freedesktop.org は {"error":"Failed to fetch: 418 I'm a teapot"} を返します。これは「ページを読めなかった」と扱い、「ページにはその記載がない」と扱ってはいけません。これは別の形で現れた「切り詰められた情報から否定的な結論を導く」罠であり、解決策は同じです。結論を出す前に、直接再取得してください。
プログラムによる存在確認
プロジェクトがモジュールごとにドキュメントページを公開している場合、存在するかどうかはステータスコードで判定でき、判断の余地はありません。これは利用できる確認方法の中で、最も信頼性が高く手間が少ないうえ、一括処理もできます。
# One plugin: 200 = exists, 404 = does not
curl -s -o /dev/null -w "%{http_code}\n" \
"https://volatility3.readthedocs.io/en/latest/volatility3.plugins.windows.idt.html"
# Every plugin the skill references, in one pass
plugins=$(grep -oE '\b(windows|linux|mac)\.[a-z_]+' SKILL.md | sort -u)
for p in $plugins; do
code=$(curl -s -o /dev/null -w "%{http_code}" \
"https://volatility3.readthedocs.io/en/latest/volatility3.plugins.$p.html")
[ "$code" = "200" ] || echo "MISSING $code $p"
done
この確認で、プラグインに関する32件の記述を数秒で検証し、存在しないものを2件見つけました。URLパターンはプロジェクトごとに調整してください。多くのドキュメント生成ツール(Sphinx、mkdocs、pkg.go.dev、docs.rs、npm、PyPI)では、シンボルまたはパッケージごとのURLが公開されており、同じ方法で確認できます。
プロジェクトにシンボルごとのドキュメントがない場合は、上流ソースで完全一致検索を行ってください。ファイルを直接取得し、grep で識別子のリテラルを検索します。どちらも決定論的な方法です。自分自身を含め、モデルに尋ねるよりもこちらを優先してください。
切り詰めによる誤検知の罠
要約ツールが「見つからない」と答えても、不在の証拠にはなりません。
大きなインデックスページを取得して、そこに何が含まれているかを尋ねたところ、Volatility の Linux プラグインインデックスについて「pslist、pstree、psaux、sockstat:記載なし」という回答が返されました。4つとも実在します。モデルがそれらの項目を見る前に、ページが切り詰められていたのです。その出力に基づいて対応していたら、正しいセクションに4つの誤りを持ち込むことになり、検証によってファイルを悪化させるところでした。
重要なのは次の非対称性です。
- 肯定的な結果は簡単です。 ツールが識別子を表示すれば、それは存在します。
- 否定的な結果は厄介です。 要約された取得結果に見当たらない場合、不在なのではなく、切り詰められている、名前が変更されている、移動されている、あるいはページ分割されている可能性があります。
したがって、要約に基づく否定的な結果を理由に、コンテンツを削除したり書き換えたりしないでください。 ファイルに手を加える前に、否定的な結果はすべて決定論的な確認にかけてください。
最も簡単な方法は、要約をやめることです。defuddle.md 経由でページを取得し、Markdown 全体を自分で grep してください。そうすれば、モデルの記憶ではなく、一致件数で答えが得られます。
L="volatility3.readthedocs.io/en/latest/volatility3.plugins.linux.html"
for p in pslist pstree psaux sockstat; do
echo "$p: $(curl -sL "https://defuddle.md/$L" | grep -c "linux\.$p module")"
done
# pslist: 1 pstree: 1 psaux: 1 sockstat: 1 -- all four present
これが、要約ツールの「記載なし」という回答を4件すべてについて覆す、まさにその確認方法です。シンボルごとのURLがある場合は、以下のステータス確認のほうがさらに確実です。どちらもできない場合は、コンテンツには手を加えず、未確認としてフラグを立ててください。未検証の記述なら後から修正できますが、正しい記述を確信を持って削除してしまうと元には戻せません。
影響度に応じた優先順位付け
すべての誤りが同じコストをもたらすわけではありません。失敗しても気づかれにくい箇所に労力をかけてください。
| 失敗の種類 | 例 | コスト |
|---|---|---|
| 明白 — 初回実行で失敗する | CLI フラグの誤り、存在しないプラグイン | 数分。ツールが知らせてくれます。 |
| 気づかれにくい — もっともらしい誤答を出す | イベント ID の誤読、保持期間の誤り、アーティファクトの意味の取り違え | 弁護士が読むインシデントの時系列記録。 |
気づかれにくい誤りにつながる記述を、何よりも優先して徹底的に検証してください。実際には、防御やフォレンジックに関する内容、つまりイベント ID、ログスキーマ、アーティファクトの意味、保持期間が優先されます。攻撃的なツールの構文のほうが危険に見えますが、これらのほうが重要です。
具体例を挙げると、M365 スキルには、E3 の Unified Audit Log の保持期間が90日と記載されていました。実際の既定値は、2023年10月以降180日です。このスキルを信頼したアナリストは、90日間の空の結果を「活動なし」と判断し、6か月分の履歴が参照できたはずの調査を終了してしまう可能性があります。
手順
- 確認可能な主張を洗い出します。 上記の種類に該当する項目、つまりコマンド、識別子、ID、フィールド名、単位付きの数値をスキルから grep します。読者が気づかない形で誤っている可能性のあるものをすべて対象にします。
- まずクラスレベルの主張を解決します(ツール名、バージョン、命名規則)。それに合わせて、以下のすべての確認範囲を見直します。
- すべての識別子を決定論的な方法で一括確認します。
- 残りの主張をティア1または2で検証し、出典を記録します。 ページを
defuddle.md経由で取得し、要約ではなく全文を手間をかけずに読めるようにします。 - 修正したうえで、変更内容と理由をコミット本文に記載します。 次の読者には、単に行が移動したのではなく、主張が確認済みであると分かる必要があります。
- 敵対的な観点から二度目の確認を行います。 修正箇所を読み直し、反証を試みます。このリポジトリでは、最初の確認で見つからず、二度目で判明した誤りがありました。自分の確認でも同じことが起きると考えてください。
- 完了した場合にのみスタンプを付けます — 以下を参照してください。
verified: スタンプ
verified: 2026-07-26 # ISO 8601; validate.py parses and counts this
このスタンプは、その日付にこのスキルの検証可能な範囲全体を一次情報源で確認したことを意味します。このスキルが優れていること、今後ずっと最新であること、あるいは完全であることを意味するものではありません。
ルール:
- 部分的な確認ではスタンプを付けません。 このリポジトリの3つの防御スキルは大幅に修正されましたが、意図的にスタンプを付けていません。いずれも、確認で主要な主張の分類は網羅したものの、ファイル全体は確認できていなかったためです。部分的な確認に完了のラベルを付けるのは、ラベルを付けないよりも悪いことです。正直な「未確認」を誤った保証に変えてしまうからです。
- 編集時ではなく、再確認時にスタンプを更新します。 セクションを追加しても、日付は更新されません。
- スタンプがないことは欠陥ではありません。
validate.pyは、スタンプがない場合を未確認の草稿として扱います。これは文書化されている既定の状態です。日付の形式が不正な場合は、件数が不正になるためエラーです。
現在の状況はいつでも確認できます。
python3 scripts/validate.py --strict # prints "Fact-checked ...: N/72"
却下すべき合理化
- 「CI が通っているから問題ありません。」 CI が確認するのは形式です。このリポジトリで見つかったエラーは、すべて CI が成功しているファイルにありました。
- 「これは自信があります。」 識別子やバージョン固有の既定値について、自信と正確さに相関はありません。Mango Markets に関する主張は、完全な自信をもって書かれていましたが、実際は逆でした。
- 「間違っていればツールがエラーを出すので、読者も気づきます。」 構文についてはそのとおりですが、解釈については違います。そして、成果物に入り込むのは解釈の誤りです。
- 「ドキュメントに記載がなかったので削除しました。」 要約された取得結果からは、内容が頻繁に抜け落ちます。何かを削除する前に、否定的な結果をステータスコードか、完全一致の grep で確認してください。
- 「すべて defuddle 経由にします。トークンを節約できます。」 defuddle は公開されている文章向けです。構造化 JSON は崩れて返され、ステータスの確認には実際のホストが必要です。また、トークン予算を満たすために、エンゲージメント URL やクライアント URL をサードパーティーのサービスに渡してはなりません。
- 「書いた時点では正しかったのです。」 保持期間、ライセンスの制限、既定のパスは、時間とともに変わります。まさにそのために確認日を記録します。「2024年には正しかった」は、2026年には弁明になりません。
- 「見つけたエラーは修正したので、スタンプを付けられます。」 スタンプを付けられるのは、検証可能な項目をすべて確認したときです。たまたま気づいたエラーがなくなったときではありません。
- 「十分近いから、読者が合わせてくれます。」 読者は、コマンドを実行するモデルや、インシデント対応でプレッシャーを受けているアナリストであることがよくあります。どちらも合わせてはくれません。
参考資料
authoring-security-skills— 新しいスキルを書く際は、スタンプを付ける前にこのスキルを使って確認しますCONTRIBUTING.md— マージ基準とプロジェクトのスタイルscripts/validate.py— 構造チェックと確認済み件数のレポート