CodeQL 用のデータベースを準備する
CodeQL は、コードをデータのように扱います。 CodeQL 分析は、コードからリレーショナル データを抽出し、それを使用して CodeQL データベースを構築することに依存します。 これらのデータベースには、コードベースに関するすべての重要な情報が含まれています。
その後、このデータベースに対して CodeQL クエリを実行して、セキュリティの脆弱性、バグ、その他のエラーを特定できます。 独自のクエリを記述することも、GitHub の研究者やコミュニティの共同作成者によって記述された標準の CodeQL クエリを実行することもできます。
スタンドアロンの CodeQL CLI を使用して、CodeQL データベースを作成および分析できます。 データベースを分析すると、静的分析結果交換形式 (SARIF) で結果が生成されます。これは、アラートの詳細を表示するためにGitHub リポジトリにアップロードできます。
CodeQL スキャン アーキテクチャ
CodeQL スキャンは、ソース コードをクエリ可能なデータに変換し、セキュリティ クエリを実行し、コード スキャン アラートとして結果を発行するパイプラインに従います。
スキャン ワークフローは次のとおりです。
- ソースコード: CodeQL は、分析中のコミットでリポジトリの内容から始まります。
- 抽出: 言語固有のエクストラクターは、コードを読み取り、ソース ファイル、構文、制御フロー、およびデータ フローに関する事実を収集します。
- データベースの作成: 抽出されたファクトは CodeQL データベースに格納されます。 各データベースは、コードベース内の 1 つの言語を表します。
- クエリの実行:CodeQL は、データベースに対してGitHub管理されたクエリ、コミュニティ クエリ、またはカスタム クエリを実行します。
- SARIF 生成: クエリ結果は、 静的分析結果交換形式 (SARIF) で書き込まれます。
- GitHubコード スキャン: SARIF の結果がGitHubにアップロードされ、コード スキャン アラートとして表示されます。
このアーキテクチャでは、コード抽出とクエリ実行を分離します。 データベースが作成されたら、コードを再度抽出することなく、同じデータベースに対して異なるクエリ スイートを実行できます。
言語戦略
CodeQL では、コンパイルされた言語と解釈された言語の両方がサポートされていますが、抽出方法は言語の種類によって異なります。
コンパイル済み言語
次のようなコンパイル済み言語の場合:
- C/C++
- C#
- Java
- Kotlin
- Rust
- Swift
- Go
CodeQL では、多くの場合、プロジェクトのビルド方法を理解する必要があります。 CodeQL では、データベースの作成時にビルド プロセスを監視して、コンパイラによって処理されたソース ファイルを抽出できます。
最も信頼性の高い結果を得るには、自動ビルド や ビルドなし オプションに頼るのではなく、明示的にビルド コマンドを設定してください。
解釈された言語
次のような解釈された言語の場合:
- Python
- JavaScript/TypeScript
- Ruby
CodeQL は、別のビルド コマンドを必要とせずに、ソース コードから直接情報を抽出します。
複数言語リポジトリ
複数のサポートされている言語を含むリポジトリの場合:
- 言語ごとに個別のデータベースを作成します。
- GitHub Actionsでは、言語マトリックスを使用して、各言語が正しく初期化、抽出、分析されるようにします。
CodeQL のデータベース準備
CodeQL データベースを生成する前に、
- CodeQL CLI をインストールして構成します。
- 分析するコードベースのバージョンを確認します。
コンパイル済み言語の場合:
- プロジェクトをビルドする準備ができていることを確認します。
- 必要なすべての依存関係を事前にインストールします。
- CodeQL は、データベースを作成するために、すべてのソース ファイルのリレーショナル表現を抽出します。
解釈される言語の場合:
- エクストラクターはソース コードで直接実行されます。
- 依存関係は、抽出中に自動的に解決されます。
コンパイル済み言語の場合、CodeQL は通常のビルド プロセスを監視します。 コンパイラがソース ファイルを処理するたびに、CodeQL によってコピーが作成され、分析に必要なすべての関連情報が抽出されます。
CLI のセットアップ
CodeQL CLI をインストールするには、次の手順に従います。
1. CodeQL CLI バンドルをダウンロードする
推奨されるインストール方法は、バンドルされたパッケージをダウンロードすることです。これにより、CLI、ライブラリ、およびクエリ パック間の互換性が保証されます。
バンドルには次のものが含まれます。
- CodeQL CLI
- 互換性のある CodeQL クエリとライブラリ
- プリコンパイル済みクエリ パック
バンドルをダウンロードするには:
- CodeQL パブリック リポジトリの [リリース] ページに移動します。
- [アセット] でプラットフォーム固有のバンドルをダウンロードします。
[リリース] ページには、次も含まれます。
- リリース ノート
- 以前のバージョン
-
codeql-bundle.tar.gzは、すべてのプラットフォームをサポートします
2. アーカイブを抽出する
.zipアーカイブを任意のディレクトリに抽出します。
macOS Catalina (またはそれ以降) のユーザーは、CodeQL CLI ドキュメントの説明に従って追加のセットアップ手順を完了する必要があります。
3. CodeQL を実行する
抽出後、次のいずれかを行います。
- Run:
<extraction-root>/codeql/codeql
または
- 追加:
<extraction-root>/codeql
システム PATH に対して次のように CLI を呼び出すことができます。
codeql
CodeQL コマンドを実行できるようになりました。
CLI のセットアップを確認する
次のコマンドを実行して、インストールが正しく動作していることを確認します。
インストールされている CodeQL パックを表示します。
codeql resolve packs
実行可能ファイルが PATHにない場合は、次のコマンドを使用します。
<extraction-root>/codeql/codeql resolve packs
必要な言語パックがない場合は、スタンドアロン CLI ではなく CodeQL バンドルをダウンロードしたことを確認します。
サポートされている言語を表示します。
codeql resolve languages
データベースの作成
プロジェクトのルートから CodeQL データベースを作成します。
codeql database create <database> --language=<language-identifier>
置換前のコード:
-
<database>を宛先ディレクトリと共に使用します。 -
<language-identifier>分析する言語の識別子を指定します。
次のオプションを使用することもできます。
| オプション | Purpose |
|---|---|
--source-root |
ソース コードを含むルート ディレクトリを指定します。 |
--db-cluster |
複数の言語のデータベースを作成します。 |
--command |
コンパイル済み言語のビルド コマンドを指定します。 Python、Ruby、または JavaScript では必要ありません。 |
--no-run-unnecessary-builds |
--db-clusterで使用する場合は、不要なビルドをスキップします。 |
正常に実行された後:
- 新しいデータベース ディレクトリが作成されます。
-
--db-clusterを使用すると、言語ごとにサブディレクトリが作成されます。
各データベースには次のものが含まれます。
- リレーショナル分析データ
- ソース アーカイブ
- CodeQL 分析に必要なメタデータ
ソース アーカイブは、データベースの作成時のソース ファイルのスナップショットであり、分析結果を表示するときに使用されます。
データベースの生成とパフォーマンスに関する考慮事項
CodeQL データベースを作成した後、データベース生成のしくみと、それがパフォーマンスに与える影響を理解することが重要です。
データベース生成メソッド
CodeQL データベースは、次のいずれかを使用して生成できます。
CodeQL コマンドラインインターフェース (CLI)
データベースを作成し、手動で分析を実行します。
この方法は、次の場合に役立ちます。
- ローカル開発
- Debugging
- 高度な構成
GitHub Actions ワークフロー
ほとんどの組織では、GitHub Actionsを使用してデータベースの生成を自動化します。
一般的なワークフロー:
- CodeQL を初期化します。
- データベースを作成します。
- クエリを実行します。
- SARIF の結果をGitHubにアップロードします。
言語ごとのデータベース
CodeQL では、サポートされている言語ごとに個別のデータベースが作成されます。
各言語:
- 独自のエクストラクターを使用します。
- 独自のデータベース スキーマを使用します。
- 個別に分析されます。
複数言語リポジトリの場合は、次のいずれかです。
- CLI で
--db-clusterオプションを使用します。 - GitHub Actionsで言語マトリックスを構成します。
言語マトリックスを使用すると、並列分析と完全な言語カバレッジが可能になります。
コンパイル済み言語のビルド ベースの抽出
コンパイル済み言語の場合:
- CodeQL はビルド プロセスを監視します。
- ビルドは正常に完了する必要があります。
- 自動 ビルド は、すべてのプロジェクトで確実に機能するわけではありません。
最適な結果を得るには、分析の前に明示的なビルド手順を定義します。
解釈された言語の場合、CodeQL はビルドを必要とせずにソース コードから直接抽出します。
パフォーマンスに関する考慮事項
データベースの作成と分析の時間は、いくつかの要因によって異なります。
リポジトリのサイズ
リポジトリが大きいほど、抽出と分析の時間が長くなります。
複数の言語
言語マトリックスを使用して、言語を並列で分析し、総実行時間を短縮します。
CI リソース
CodeQL 分析は、リソースを大量に消費する場合があります。
ランナーの CPU またはメモリを増やすと、パフォーマンスが大幅に向上する可能性があります。
分析の範囲
スキャンされるコードを制限することで、分析時間を短縮できます。たとえば、次を除外します。
- テスト ファイル
- 生成されたコード
一般に、分析時間は、処理されるソース コードの量に比例します。
データベースの作成と再生成
CodeQL データベースは、特定の時点でのコードベースのスナップショットを表します。
- 分析の実行ごとに新しいデータベースが作成されます。
- データベースは増分更新されません。
- コードベースを変更するには、新しいデータベースが必要です。
通常、次の場合にデータベースを再生成します。
- 新しいコミットがプッシュされます。
- プルリクエストが作成または更新されます。
- ビルド構成の変更。
- クエリ セットまたは分析構成の変更。
データベースの生成は各スキャンの一部であるため、プル要求やスケジュールされた実行などの意味のあるイベントにスキャンを合わせることが重要です。
抽出器
エクストラクターは、CodeQL データベースの構築元となる各入力ファイルのリレーショナル データとソース参照を生成するツールです。 CodeQL でサポートされる各言語には、1 つのエクストラクターがあります。 この構造により、抽出プロセスが可能な限り正確になります。
各エクストラクターでは、独自の構成オプション セットを定義します。
codeql resolve extractor --format=betterjson入力すると、次の例のようにデータが書式設定されます。
{
"extractor_root": "/home/user/codeql/java",
"extractor_options": {
"option1": {
"title": "Java extractor option 1",
"description": "An example string option for the Java extractor.",
"type": "string",
"pattern": "[a-z]+"
},
"group1": {
"title": "Java extractor group 1",
"description": "An example option group for the Java extractor.",
"type": "object",
"properties": {
"option2": {
"title": "Java extractor option 2",
"description": "An example array option for the Java extractor",
"type": "array",
"pattern": "[1-9][0-9]*"
}
}
}
}
}
言語のエクストラクターで使用できるオプションを確認するには、次のように入力します。
-
codeql resolve languages --format=betterjson、または -
codeql resolve extractor --format=betterjson。
betterjson出力形式には、エクストラクターのルートやその他の言語固有のオプションも用意されています。
CodeQL データベース内のデータ
CodeQL データベースは、分析に必要なすべてのデータを含む 1 つのディレクトリです。 このデータには、リレーショナル データ、コピーされたソース ファイル、およびデータ内の相互関係を指定する言語固有のデータベース スキーマが含まれます。 CodeQL は、抽出後にこのデータをインポートします。
CodeQL データベースは、コードベースから抽出された特定の言語のクエリ可能なデータのスナップショットを提供します。 このデータは、コードの完全な階層表現です。 次の機能が含まれます。
- 抽象構文ツリー (AST) の表現。
- データ フロー グラフ。
- 制御フロー グラフ。
データベースは、複数言語のコードベースに対して一度に 1 つの言語で生成されます。 各言語には、独自の一意のデータベース スキーマがあります。 スキーマは、抽出プロセス中の最初の字句分析と CodeQL による複雑な分析の間のインターフェイスを提供します。
CodeQL データベースには、次の 2 つのメイン テーブルが含まれています。
- 式テーブルには、ビルド プロセス中に CodeQL によって分析されたソース コード内のすべての式の行が含まれています。
- ステートメント テーブルには、CodeQL がビルド プロセス中に分析したソース コード内のすべてのステートメントの行が含まれています。
CodeQL ライブラリは、これらの各テーブルに抽象化レイヤーを提供するクラスを定義します。 このレイヤーには、関連する補助テーブル Expr と Stmtが含まれます。
CodeQL の不足の可能性
コード スキャン ワークフローでのデータベースの作成には、いくつかの不足が考えられます。 このセクションでは、GitHub CodeQL アクションの使用について具体的に説明します。
自動ビルド用の言語マトリックスを使用して、マトリックスに一覧表示されているコンパイル済みの各言語をビルドする必要があります。 マトリックスを使用して、サポートされている複数のバージョンのプログラミング言語、オペレーティング システム、またはツールのジョブを作成できます。
マトリックスを使用しない場合、自動ビルドでは、リポジトリ内の最も多くのソース ファイルを使用して、サポートされているコンパイル済み言語のビルドが試みられます。 Go 以外のコンパイル済み言語の分析は、多くの場合、分析手順を実行する前にコードをビルドするための明示的なコマンドを指定しない限り失敗します。
自動ビルド 手順の動作は、言語エクストラクターが実行されているオペレーティング システムによって異なります。 自動ビルドの手順では、オペレーティング システムに基づいて言語に適したビルド方法が自動的に検出されます。 この動作により、コンパイルされた言語で信頼性の低い結果が得られ、多くの場合、実行が失敗する可能性があります。
自動ビルドでコンパイルされた言語をビルドするのではなく、分析前に実行されるコード スキャン ワークフロー ファイル内でビルド ステップを構成することをお勧めします。 これにより、ワークフロー ファイルは、システムとプロジェクトのビルド要件に合わせて調整され、より信頼性の高いスキャンが可能になります。
特定の言語と自動ビルドの手順の詳細については、CodeQL の自動ビルドに関するドキュメントを参照してください。
VS Code 拡張機能
VS Code 1.39 以降を使用している限り、Visual Studio Code (VS Code) と CodeQL 拡張機能を使用してクエリをコンパイルして実行できます。 Visual Studio Code Marketplace から、または CodeQL VSIX ファイルをダウンロードして、拡張機能をダウンロードできます。
この拡張機能では、 PATH で見つかったインストール済みの CLI (使用可能な場合) が使用されます。 そうでない場合、拡張機能は CLI の実行可能ファイルへのアクセスを自動的に管理します。 自動管理により、CLI は CodeQL 拡張機能と互換性があります。