codeql について
複数のプログラミング言語を対象とする、セキュリティ分析用の CodeQL スキルです。データベースの構築、クエリの選択、結果の確認を行う開発者向けに、データベース品質、プロジェクト固有のデータ拡張、クエリスイートの明示的な検証を重視します。
主な機能
- 01CodeQL データベースの構築と評価
- 02プロジェクト API 向けデータ拡張の作成
- 03ルールセットの選択とクエリ実行
- 04クエリスイートとデータベース品質の検証
- 05分析成果物とレポートの整理
活用シーン
- 01コードベースのセキュリティ問題を調べる
- 02CodeQL データベースを再利用または新規作成する
- 03データ拡張でフレームワーク固有 API をモデル化する
- 04ビルド品質の不足や結果ゼロの分析を調査する
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ trailofbits/ skills --skill codeqlインストール後、Claude Code で/codeqlを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
agents/openai.yamlassets/trail-of-bits-mark.svgreferences/build-fixes.mddiagnostic-query-templates.mdextension-yaml-format.mdimportant-only-suite.mdlanguage-details.mdmacos-arm64e-workaround.mdperformance-tuning.mdquality-assessment.mdruleset-catalog.mdrun-all-suite.mdsarif-processing.mdthreat-models.mdscripts/build_log.shcheck_db_quality.pyfind_databases.shgenerate_suite.shpyproject.tomltest_build_log.pytest_build_mode_claims.pytest_check_db_quality.pytest_find_databases.pytest_generation_scripts.pytest_script_flags.pytest_section_pointers.pytest_shell_blocks.pytest_suite_templates.pytest_verify_query_suite.pyverify_query_suite.py詳細
CodeQL 分析
対応言語:Python、JavaScript/TypeScript、Go、Java/Kotlin、C/C++、C#、Ruby、Swift。
スキルリソース: リファレンスファイルとテンプレートは {baseDir}/references/ および {baseDir}/workflows/ にあります。
重要な原則
-
データベースの品質は妥協できません。 ビルドが成功したデータベースが、必ずしも良質とは限りません。キャッシュされたビルドでは、成功を報告しながら何も抽出されていない場合があります。
-
データ拡張により、CodeQL が見逃す問題を検出できます。 Django、Spring、Express のプロジェクトでは、出荷済みのモデルでは対応していないプロジェクト固有の API に、データベース呼び出し、リクエストの解析、シェル実行がラップされている場合があります。
-
スイートを明示的に指定すると、クエリが暗黙に除外されるのを防げます。
codeql database analyzeにパック名を渡さないでください。各パックのdefaultSuiteFileでは、結果がゼロになる可能性のある非表示のフィルターが適用されます。必ず.qlsを生成してください。 -
検出結果がゼロの場合は、喜ぶのではなく調査が必要です。 抽出の品質が低い、モデルが不足している、パックが誤っている、またはスイートでフィルターされている可能性があります。ビルド後に
{baseDir}/scripts/check_db_quality.pyを実行し、使用中のスイートに対して{baseDir}/scripts/verify_query_suite.pyがゼロで終了したことを確認してください。生成スクリプトではこれを実行するため、再利用するスイートまたは手動編集したスイートに対してのみ、手動で実行してください。レポートには、両方のチェックに合格したことを記載してください。 -
macOS の Apple Silicon でコンパイル言語を使う場合は、回避策が必要です。 終了コード 137 はビルド失敗ではなく、
arm64eとarm64の不一致を示しています。build-mode=noneに切り替える前に、Homebrew の arm64 ツールまたは Rosetta を試してください。 -
ワークフローは手順どおりに進めてください。 各フェーズが次のフェーズの実行条件になっています。品質評価やデータ拡張を省略すると、結果に現れない問題が残ります。
Bash の呼び出しごとに新しいシェルが起動します
Bash の呼び出しをまたいで引き継がれるものはありません。変数、配列、build_log.sh から読み込んだ関数も引き継がれません。以下の各ブロックで値を使用する場合は、同じブロック内で設定し直してください。ワークフローではこの説明を繰り返さず、ここを参照しています。各ケースで異なる問題が発生し、いずれも気付かれないまま失敗するため、ここではその具体的な影響を説明します。
- 関数が失われると、
run_loggedは終了コード 127 で終了します。ビルド手順ではこれを失敗した方法として扱い、--build-mode=noneまで順に進んでしまい、CodeQL は実行されません。 - 配列が失われると、何も展開されません。そのため、ユーザーが選択したすべての
--threat-modelと--model-packsが無視される一方、最終レポートには使用したと記載されます。 set -uのもとで スカラーが失われると、unbound variableでブロックが中断されます。
出力ディレクトリ
生成されるすべてのファイル(データベース、ビルドログ、診断情報、拡張機能、結果)は、1 つの出力ディレクトリに保存されます。
- ユーザーがプロンプトで出力ディレクトリを指定した場合は、それを
OUTPUT_DIRとして使用します。 - 指定がない場合は、
./static_analysis_codeql_1をデフォルトとして使用します。すでに存在する場合は、_2、_3のように番号を増やします。
どちらの場合も、ファイルを書き込む前に必ず mkdir -p でディレクトリを作成してください。
これを実行する前に、USER_SPECIFIED_DIR にユーザーのプロンプトに記載されたパスをそのまま設定してください。自動で番号を増やす場合は、設定しないでください。これ以外の箇所でこの変数に値を代入しないでください。
# Resolve output directory
USER_SPECIFIED_DIR="${USER_SPECIFIED_DIR:-}" # substitute the user's path here, if any
if [ -n "$USER_SPECIFIED_DIR" ]; then
OUTPUT_DIR="$USER_SPECIFIED_DIR"
else
BASE="static_analysis_codeql"
N=1
while [ -e "${BASE}_${N}" ]; do
N=$((N + 1))
done
OUTPUT_DIR="${BASE}_${N}"
fi
mkdir -p "$OUTPUT_DIR"
出力ディレクトリは、ワークフローを実行する前の開始時に一度だけ決定されます。すべてのワークフローには $OUTPUT_DIR が渡され、生成物はそのディレクトリに保存されます。
$OUTPUT_DIR/
├── rulesets.txt # Selected query packs (logged after Step 3)
├── codeql.db/ # CodeQL database (dir containing codeql-database.yml)
├── build.log # Build log
├── codeql-config.yml # Exclusion config (interpreted languages)
├── diagnostics/ # Diagnostic queries and CSVs
├── extensions/ # Data extension YAMLs
├── raw/ # Unfiltered analysis output
│ ├── results.sarif
│ └── run-all.qls | important-only.qls
└── results/ # Final results (filtered for important-only, copied for run-all)
└── results.sarif
データベースの検出
CodeQL データベースは、そのディレクトリ内に codeql-database.yml マーカーファイルが存在することで識別できます。既存のデータベースを検索するときは、一致したものを必ずすべて収集してください。以前の実行で作成されたデータベースや、言語ごとに複数のデータベースが存在する場合があります。
検出コマンド。 find_databases.sh は、ビルドに失敗したときに残るマーカーファイルを除外し、データベースのパスを1行ずつ出力します。配列は、そこから選択するのと同じブロック内で構築してください。Bash の呼び出しごとに新しいシェルが起動するため、ここで構築した配列は次の呼び出しでは空になり、データベースが存在しないという結論になります。
# Command substitution, not `done < <(...)`: a process substitution discards the script's
# exit status, so "codeql is not on this shell's PATH" (exit 2) would arrive as an empty
# list and route to "build a new database" with three good ones sitting on disk.
if ! DB_LIST=$("{baseDir}/scripts/find_databases.sh" "${OUTPUT_DIR:-.}" .); then
echo "ERROR: database discovery failed — see the message above" >&2
exit 1
fi
FOUND_DBS=()
while IFS= read -r db; do
[ -n "$db" ] || continue
FOUND_DBS+=("$db")
done <<<"$DB_LIST"
echo "Found ${#FOUND_DBS[@]} existing database(s)"
# The metadata the selection prompt needs, collected here rather than in a block of its
# own: FOUND_DBS is gone by the next Bash call, and a loop over an array that no longer
# exists prints nothing and reports success.
for db in "${FOUND_DBS[@]}"; do
CODEQL_LANG=$(codeql resolve database --format=json -- "$db" 2>/dev/null | jq -r '.languages[0]')
CREATED=$(grep '^creationMetadata:' -A5 "$db/codeql-database.yml" 2>/dev/null | grep 'creationTime' | awk '{print $2}')
echo "$db — language: $CODEQL_LANG, created: $CREATED"
done
データベース名が codeql.db だと決めつけないでください。マーカーファイルを使って検出してください。
複数のデータベースが見つかった場合: AskUserQuestion を使って、上に表示された言語と作成時刻をもとに、使用するデータベースを選択するか、新しいデータベースを構築するかをユーザーに選んでもらいます。AskUserQuestion の選択肢は最大4つです。データベースがそれより多い場合は、最も新しい3つと「新しいデータベースを構築する」を提示し、残りはプロンプト本文に列挙してください。ユーザーがプロンプトで使用するデータベース、または新しいデータベースを構築することを明示している場合は、AskUserQuestion を省略してください。
クイックスタート
よくあるケース(「このコードベースをスキャンして脆弱性を検出する」)の場合:
# Verify CodeQL is installed. Stop here if it is not — every later command fails with
# a less informative error, and the run wastes a build cycle before saying why.
if ! command -v codeql >/dev/null 2>&1; then
echo "ERROR: codeql not found on PATH. Install it with one of:" >&2
echo " gh extension install github/gh-codeql # then: gh codeql install-stub" >&2
echo " brew install --cask codeql" >&2
echo " https://github.com/github/codeql-action/releases (codeql-bundle)" >&2
exit 1
fi
# jq parses `codeql resolve database --format=json` in the very next step. Without it
# CODEQL_LANG comes back empty and the run continues against the wrong language.
if ! command -v jq >/dev/null 2>&1; then
echo "ERROR: jq not found on PATH (brew install jq / apt install jq)" >&2
exit 1
fi
# uv runs both guard scripts and both suite generators. Check it here rather than at
# suite generation, which is after the build — otherwise a machine without uv spends
# the whole build before failing.
if ! command -v uv >/dev/null 2>&1; then
echo "ERROR: uv not found on PATH (https://docs.astral.sh/uv/getting-started/)" >&2
exit 1
fi
codeql --version
次に、上記の出力ディレクトリのブロックを使って OUTPUT_DIR を解決してください。単純な自動採番とは異なり、ユーザーが指定したディレクトリが反映されます。
続いて、以下のワークフローを使って、パイプライン全体を実行します。データベースを構築 → データ拡張を作成 → 分析を実行。
退けるべき誤った理屈
これらの近道は検出漏れにつながります。受け入れないでください。
- 「security-extended で十分」 — これはベースラインです。その言語で Trail of Bits パックと Community Packs が利用できるか、必ず確認してください。これらは
security-extendedではまったく検出できないカテゴリを検出します。 - 「security-and-quality が最も網羅的なスイート」 —
security-and-qualityはすべてのexperimental/クエリパスを除外します。全件実行モードでは、security-and-qualityとsecurity-experimentalの両方をインポートしてください。差分は言語によって1〜52件のクエリです。 - 「データベースを構築できたので問題ない」 — データベースを構築できても、抽出が適切に行われたとは限りません。必ず品質評価を実行し、ファイル数を想定されるソースファイルと照合してください。
- 「標準的なフレームワークならデータ拡張は不要」 — Django や Spring のアプリにも、CodeQL がモデル化していない独自のラッパーが存在します。拡張を省略すると、脆弱性を見逃します。
- 「コンパイル言語でも build-mode=none で問題ない」 — 分析が著しく不完全になります。最後の手段としてのみ使用してください。macOS では、まず arm64 ツールチェーンの回避策か Rosetta を試してください。
- 「macOS でビルドに失敗したので、build-mode=none を使えばよい」 — 終了コード137の原因は
arm64e/arm64の不一致であり、根本的なビルド失敗ではありません。macOS arm64e の回避策を参照してください。 - 「検出結果がないので、コードは安全だ」 —
check_db_quality.pyとverify_query_suite.pyを実行し、合格したことを報告してください。これらを実行しなければ、検出結果がゼロである場合と、データベースから何も抽出されなかった場合は、同じ結果になります。 - 「デフォルトのスイートを実行すればよい」/「パック名を直接渡せばよい」 — 各パックの
defaultSuiteFileは見えないフィルターを適用するため、結果がゼロになることがあります。必ず明示的なスイート参照を使用してください。 - 「ファイルは現在のディレクトリに置けばよい」 — 生成したファイルはすべて
$OUTPUT_DIRに置いてください。作業ディレクトリにファイルを散在させると、クリーンアップが困難になり、以前の実行結果を上書きするおそれがあります。 - 「見つかった最初のデータベースを使えばよい」 — 言語ごと、または以前の実行によって、複数のデータベースが存在する場合があります。複数見つかった場合は、すべての選択肢をユーザーに提示してください。プロンプトを省略できるのは、ユーザーが使用するデータベースをすでに指定している場合のみです。
- 「ユーザーが『スキャン』と言ったのだから、使うデータベースを選んでほしいということだ」 — 「スキャン」はデータベースの選択を意味しません。複数のデータベースが存在し、ユーザーがどれを使うか指定していない場合は、確認してください。
ワークフローの選択
このスキルには3つのワークフローがあります。ワークフローを選択したら、フェーズを飛ばさず、順番に実行してください。
これらの実行には時間がかかります。データベースのビルドには4つのフォールバック方法があるため、タスクツールを使って進捗を追跡してください。実行内容に応じて、追跡する価値のあるステップを判断してください。
| ワークフロー | 目的 |
|---|---|
| build-database | ビルド方法を順に試してCodeQLデータベースを作成します |
| create-data-extensions | プロジェクトのAPI向けデータ拡張モデルを検出または生成します |
| run-analysis | ルールセットを選択し、クエリを実行して、結果を処理します |
無人でのビルド
このプラグインには /static-analysis:codeql-build が付属しており、build-databaseの手順を最初から最後まで実行します。言語とツールチェーンを検出し、方法を順に試しながら各段階の間に build-fixes.md の修正を適用し、品質ゲートを適用します。
/static-analysis:codeql-build {"target": "/abs/path", "lang": "cpp"}
何も尋ねません。すべての方法が失敗した場合や、ビルドされたデータベースが品質しきい値を下回った場合は、no-method-succeeded および built-below-threshold のステータスが返されるため、ここで対応できます。残ったエクストラクターエラーが、分析する必要のないコードに限られるかどうかは、実行側では判断できないためです。
ビルドに時間がかかり、結果が不確実な場合に、結論が出るまで任せたいなら、この方法を使ってください。どの方法を試すかを自分で決めたい場合や、ビルドの失敗を発生時に解釈する必要がある場合は、build-database.md の手順を手動で進めてください。
自動検出ロジック
ユーザーが実行内容を明示している場合(例:「データベースをビルドして」「./my-db で分析を実行して」)は、該当するワークフローを直接実行してください。ユーザーのプロンプトから意図が明確な場合は、データベースの選択について AskUserQuestion を呼び出さないでください。例:「新しいデータベースをビルドして」「static_analysis_codeql_2 の codeql データベースを分析して」「最初からフルスキャンを実行して」。
「test」「scan」「analyze」などのデフォルトパイプライン: 上記の データベースの検出 に記載されたコマンドで既存のデータベースを検出してから、次のように判断してください。
| 条件 | アクション |
|---|---|
| データベースが見つからない | 新しい $OUTPUT_DIR を解決し、ビルド → 拡張 → 分析(フルパイプライン)を実行します |
| データベースが1つ見つかった | AskUserQuestion を使い、再利用するか新規作成するかを尋ねます |
| 複数のデータベースが見つかった | データベースの検出 を参照し、選択肢を最大4つにして AskUserQuestion を使います |
| ユーザーが意図を明示している | AskUserQuestion を省略し、指示どおりに実行します |
データベース選択の質問
既存のデータベースが見つかり、ユーザーがどれを使うか明示していない場合は、AskUserQuestion を使い、「Existing CodeQL Databases」というヘッダーの下に表示してください。各選択肢には、上記で取得したパス、言語、作成時刻を含めてください。例:./static_analysis_codeql_1/codeql.db (language: python, created: 2026-02-24)。最後の選択肢は「Build a new database」にしてください。
選択後:
- ユーザーが既存のデータベースを選んだ場合:
$OUTPUT_DIRをその親ディレクトリ(またはデータベースを含むディレクトリ)に設定し、$DB_NAMEを選択されたパスに設定してから、拡張 → 分析に進みます。 - ユーザーが「Build new」を選んだ場合: 新しい
$OUTPUT_DIRを解決し、ビルド → 拡張 → 分析を実行します。
一般的な選択の質問
データベースとワークフローのどちらもプロンプトから明確でない場合は、AskUserQuestion を使い、4つのワークフロー(フルスキャン(推奨)、データベースのビルド、データ拡張の作成、分析の実行)を提示してください。見つかったデータベースと、解決した $OUTPUT_DIR も示してください。
参照インデックス
| ファイル | 内容 |
|---|---|
| スクリプト | |
| scripts/verify_query_suite.py | クエリ数がゼロになるスイートを失敗とします。生成スクリプトから実行されます。再利用するスイート、または手動で編集したスイートに対してのみ、手動で実行してください |
| scripts/check_db_quality.py | 解析可能なソースがないデータベースを失敗とします。ビルドのたびに実行してください |
| scripts/build_log.sh | log_step/run_logged ヘルパーです。ビルド手順を実行する前に source してください |
| scripts/find_databases.sh | codeql resolve database が受け付けるすべてのデータベースを、1 行に 1 つずつ出力します。これを読み取るブロック内で、出力から配列を構築してください |
| scripts/generate_suite.sh | run-all または important-only の .qls を書き込み、解決後のクエリ数がゼロでないことを検証します |
| 参照資料 — 3 つのワークフローは ワークフローの選択 に記載されています | |
| references/macos-arm64e-workaround.md | Apple Silicon でのビルドトレースの回避策 |
| references/build-fixes.md | ビルド失敗の修正カタログ |
| references/quality-assessment.md | データベースの品質指標と改善策 |
| references/extension-yaml-format.md | データ拡張 YAML の列定義と例 |
| references/sarif-processing.md | SARIF 出力を処理する jq コマンド |
| references/diagnostic-query-templates.md | ソース/シンクを列挙する QL クエリ |
| references/important-only-suite.md | important-only スイートのテンプレートと生成 |
| references/run-all-suite.md | run-all スイートのテンプレート |
| references/ruleset-catalog.md | 言語別に利用可能なクエリパック |
| references/threat-models.md | 脅威モデルの設定 |
| references/language-details.md | 言語固有のビルドと抽出の詳細 |
| references/performance-tuning.md | メモリ、スレッド、タイムアウトの設定 |
成功基準
CodeQL の分析を完全に実行するには、次の条件を満たす必要があります。
- 出力ディレクトリが解決されている(ユーザー指定、または自動採番されたデフォルト)
- 生成されたすべてのファイルが
$OUTPUT_DIR内に保存されている - データベースがビルドされ(
codeql-database.ymlマーカーで検出)、{baseDir}/scripts/check_db_quality.pyが終了コード 0 で終了している - データ拡張が評価されている —
$OUTPUT_DIR/extensions/に作成されているか、正当な理由を添えて明示的にスキップされている - 明示的なスイート参照(デフォルトのパックのスイートではない)を指定して分析を実行し、そのスイートに対して
{baseDir}/scripts/verify_query_suite.pyが終了コード 0 で終了している - インストール済みのすべてのクエリパック(公式、Trail of Bits、Community)が使用されているか、明示的に除外されている
- 選択したクエリパックが
$OUTPUT_DIR/rulesets.txtに記録されている - フィルター前の結果が
$OUTPUT_DIR/raw/results.sarifに保持されている - 最終結果が
$OUTPUT_DIR/results/results.sarifに保存されている(important-only の場合はフィルター処理し、run-all の場合はコピー) - 検出結果がゼロの場合に調査されている(データベースの品質、モデルのカバレッジ、スイートの選択)
- すべてのコマンド、修正、品質評価を含むビルドログが
$OUTPUT_DIR/build.logに保持されている