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でブロックを中断します
出力ディレクトリ
生成されたすべてのファイル(データベース、ビルドログ、診断情報、拡張、結果)は単一の出力ディレクトリに保存されます。
- ユーザーがプロンプトで出力ディレクトリを指定した場合、それを
OUTPUT_DIRとして使用します。 - 指定されていない場合、デフォルトで
./static_analysis_codeql_1にします。すでに存在する場合は_2、_3のようにインクリメントします。
どちらの場合も、ファイルを書き込む前に 必ず mkdir -p でディレクトリを作成 してください。
これを実行する前に USER_SPECIFIED_DIR をユーザーのプロンプトからのリテラルパスに設定するか、自動インクリメントのために未設定のままにしてください。他の何もこれを割り当てません。
# 出力ディレクトリの解決
USER_SPECIFIED_DIR="${USER_SPECIFIED_DIR:-}" # ここにユーザーのパスがあれば代入
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 # 選択されたクエリパック(ステップ3後に記録)
├── codeql.db/ # CodeQL データベース(codeql-database.yml を含むディレクトリ)
├── build.log # ビルドログ
├── codeql-config.yml # 除外設定(インタプリタ言語)
├── diagnostics/ # 診断クエリとCSV
├── extensions/ # データ拡張 YAML
├── raw/ # フィルタリングされていない分析出力
│ ├── results.sarif
│ └── run-all.qls | important-only.qls
└── results/ # 最終結果(important-only の場合はフィルタリング、run-all の場合はコピー)
└── results.sarif
データベースの発見
CodeQL データベースは、そのディレクトリ内に codeql-database.yml マーカーファイルが存在することによって識別されます。既存のデータベースを検索するときは、常にすべての一致を収集 してください — 以前の実行や異なる言語の複数のデータベースが存在する可能性があります。
発見コマンド。 find_databases.sh はデータベースパスを1行に1つ出力し、失敗したビルドが残すマーカーファイルをフィルタリングします。配列は その配列から選択するのと同じブロック内で 構築してください — 各 Bash 呼び出しは新しいシェルであるため、ここで構築された配列は次の呼び出しまでに空になり、実行はデータベースがないと結論付けます:
# コマンド置換、`done < <(...)` ではありません: プロセス置換はスクリプトの終了ステータスを破棄するため、
# "codeql is not on this shell's PATH"(終了コード2)は空のリストとして到着し、
# ディスクに3つの有効なデータベースがあるにもかかわらず「新しいデータベースをビルド」にルーティングされます。
if ! DB_LIST=$("{baseDir}/scripts/find_databases.sh" "${OUTPUT_DIR:-.}" .); then
echo "ERROR: データベース発見に失敗しました — 上記のメッセージを確認してください" >&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)"
# 選択プロンプトに必要なメタデータ。FOUND_DBS は次の Bash 呼び出しまでに
# 消えているため、ループは存在しない配列に対して何も出力せず成功を報告します。
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 — 言語: $CODEQL_LANG, 作成日時: $CREATED"
done
データベースが codeql.db という名前であると決して想定しないでください — マーカーファイルで発見してください。
複数のデータベースが見つかった場合: 上記で出力された言語と作成日時を使用して、AskUserQuestion でユーザーにどのデータベースを使用するか、または新しいものをビルドするかを選択させます。AskUserQuestion は最大4つのオプションを受け付けるため、それ以上のデータベースがある場合は、最新の3つと「新しいデータベースをビルド」を提供し、残りはプロンプトテキストにリストします。ユーザーがプロンプトで使用するデータベースを明示的に指定した場合、または新しいデータベースをビルドすると指定した場合は AskUserQuestion をスキップしてください。
クイックスタート
一般的なケース(「このコードベースの脆弱性をスキャン」)の場合:
# CodeQL がインストールされていることを確認。ここで停止 — それ以降のすべてのコマンドは
# 情報量の少ないエラーで失敗し、実行は理由を説明する前にビルドサイクルを無駄にします。
if ! command -v codeql >/dev/null 2>&1; then
echo "ERROR: codeql が PATH に見つかりません。以下のいずれかでインストールしてください:" >&2
echo " gh extension install github/gh-codeql # その後: 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 は次のステップで `codeql resolve database --format=json` を解析します。これがないと
# CODEQL_LANG は空で返り、実行は間違った言語に対して続行されます。
if ! command -v jq >/dev/null 2>&1; then
echo "ERROR: jq が PATH に見つかりません (brew install jq / apt install jq)" >&2
exit 1
fi
# uv はガードスクリプトとスイートジェネレーターの両方を実行します。
# スイート生成(ビルド後)ではなくここで確認 — そうしないと uv のないマシンは
# ビルド全体を費やしてから失敗します。
if ! command -v uv >/dev/null 2>&1; then
echo "ERROR: uv が PATH に見つかりません (https://docs.astral.sh/uv/getting-started/)" >&2
exit 1
fi
codeql --version
次に、上記の出力ディレクトリのブロックを使用して OUTPUT_DIR を解決します — ユーザー指定のディレクトリが優先され、単なる自動インクリメントは行われません。
次に、以下のワークフローを使用して完全なパイプラインを実行します: データベースのビルド → データ拡張の作成 → 分析の実行
拒否すべき合理化
これらの近道は検出結果の見逃しにつながります。受け入れないでください:
- 「security-extended で十分です」 - それはベースラインです。言語に対して Trail of Bits パックとコミュニティパックが利用可能かどうかを常に確認してください。これらは
security-extendedが完全に見逃すカテゴリをキャッチします。 - 「security-and-quality が最も広範なスイートです」 -
security-and-qualityはすべてのexperimental/クエリパスを除外します。run-all モードでは、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-workaround.md を参照してください。 - 「検出結果がないということは、コードが安全であることを意味します」 -
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-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 データベースを分析」、「最初からフルスキャンを実行」。
「テスト」、「スキャン」、「分析」などに対するデフォルトパイプライン: 上記のデータベースの発見のコマンドを使用して既存のデータベースを発見し、次のように決定します。
| 条件 | アクション |
|---|---|
| データベースが見つからない | 新しい $OUTPUT_DIR を解決し、ビルド → 拡張 → 分析を実行(完全パイプライン) |
| 1つのデータベースが見つかった | AskUserQuestion を使用: 再利用するか新規ビルドするか? |
| 複数のデータベースが見つかった | AskUserQuestion を使用、最大4つのオプション — データベースの発見を参照 |
| ユーザーが明示的に意図を指定した | AskUserQuestion をスキップし、指示に直接従う |
データベース選択プロンプト
既存のデータベースが見つかり ユーザーが使用するものを明示的に指定しなかった場合、「Existing CodeQL Databases」というヘッダーのもとで AskUserQuestion を使用してそれらを提示します。各オプションには、上記で収集したパス、言語、作成日時をラベル付けします — ./static_analysis_codeql_1/codeql.db (言語: python, 作成日時: 2026-02-24) — そして最後のオプションを「Build a new database」にします。
選択後:
- ユーザーが既存のデータベースを選択した場合:
$OUTPUT_DIRをその親ディレクトリ(またはそれを含むディレクトリ)に設定し、$DB_NAMEを選択されたパスに設定し、拡張 → 分析に進みます。 - ユーザーが「Build new」を選択した場合: 新しい
$OUTPUT_DIRを解決し、ビルド → 拡張 → 分析を実行します。
一般的な決定プロンプト
プロンプトからデータベースもワークフローも明確でない場合は、AskUserQestion を介して4つのワークフローを提供します。
...