Skip to main content

CodeQL 分析のためのコードの準備

コードの分析に必要なデータが含まれた CodeQL データベースを作成できます。

この機能を使用できるユーザーについて

リポジトリへの読み取りアクセス権を持つユーザー

CodeQL は、次の種類のリポジトリで使用できます:

分析のためのコードの準備について

Note

この記事では、GitHub Enterprise Server 3.11 の初期リリースに含まれている CodeQL CLI 2.14.6 バンドルで使用できる機能について説明します。

サイト管理者が CodeQL CLI のバージョンをより新しいリリースに更新している場合は、この記事の GitHub Enterprise Cloud バージョンで最新の機能に関する情報を参照してください。

CodeQL を使用してコードを分析する前に、コードに対してクエリを実行するために必要なすべてのデータが含まれた CodeQL データベースを作成する必要があります。 CodeQL CLI を使い、CodeQL データベースを自分で作成できます。

CodeQL の分析は、コードからリレーショナル データを抽出し、それを使用して CodeQL データベースを構築することに依存しています。 CodeQL データベースには、コードベースに関するすべての重要な情報が含まれており、CodeQL クエリを実行することでそれを分析できます。

CodeQL データベースを生成する前に、次のことを行う必要があります。

  1. CodeQL CLI をインストールして設定する。 詳しくは、「CodeQL CLI の設定」を参照してください。
  2. 分析するコードをチェックアウトします。
    • ブランチの場合は、分析するブランチのヘッドをチェックアウトします。
    • pull request の場合は、pull request のヘッド コミットをチェックアウトするか、GitHub で生成された pull request のマージ コミットをチェックアウトします。
  3. コードベースの環境を設定し、依存関係が使用可能であることを確認します。
  4. コンパイル型言語で最適な結果を得るには、コードベースのビルド コマンドを見つけます (存在する場合)。 通常、これは CI システムの構成ファイルで使用できます。

コードベースの準備ができたら、codeql database create を実行してデータベースを作成できます。 詳しくは、「コンパイルされていない言語のデータベースの作成」および「コンパイル済み言語のデータベースの作成」を参照してください。

実行中 codeql database create

プロジェクトのチェックアウト ルートから次のコマンドを実行すると、CodeQL データベースが作成されます。

codeql database create <database> --language=<language-identifier>

ユーザーは次のものを指定する必要があります。

  • <database>: 作成する新しいデータベースへのパス。 このコマンドを実行すると、このディレクトリが作成されます。既存のディレクトリを指定することはできません。

  • --language: どの言語のデータベースを作成するかを表す識別子。 --db-cluster と一緒に使用する場合は、オプションでコンマ区切りリストが受け入れられるか、複数指定できます。 CodeQL では、次の言語のデータベースの作成がサポートされています。

    言語識別子
    C/C++cpp
    C#csharp
    Gogo
    Java/Kotlinjava
    JavaScript/TypeScriptjavascript
    Pythonpython
    Rubyruby
    Swiftswift

コードベースにビルド プロセスを呼び出すビルド コマンドまたはスクリプトがある場合は、次のように指定することをお勧めします。

   codeql database create <database> --command <build> \
         --language=<language-identifier>

データベースを作成するためのオプション

ソース ファイルの場所、コードをコンパイルする必要があるかどうか、複数の言語の CodeQL データベースを作成するかどうかに応じて、追加のオプションを指定できます。

オプション必須使用法
<database>CodeQLデータベースを作成するディレクトリの名前と場所を指定します。 既存のディレクトリを上書きしようとすると、コマンドは失敗します。 また --db-cluster を指定した場合は、これが親ディレクトリであり、分析される言語ごとにサブディレクトリが作成されます。
--languageデータベースを作成する言語の識別子として、次のいずれかを指定します: cppcsharpgojavajavascriptpythonruby、および swift (TypeScript コードを分析するには javascript、Kotlin コードを分析するには java を使用します)。 --db-cluster と一緒に使用する場合は、オプションでコンマ区切りリストが受け入れられるか、複数指定できます。
--command推奨。 コードベースのビルド プロセスを呼び出すビルド コマンドまたはスクリプトを指定するために使用します。 コマンドは、現在のフォルダーまたは、定義されている場合は、--source-root から実行されます。 Python および JavaScript または TypeScript の分析には不要です。
--db-cluster--language によって指定された言語ごとに 1 つのデータベースを生成するには、複数言語コードベースを使用します。
--no-run-unnecessary-builds推奨。 CodeQL CLIがビルドをモニターする必要がない場合に、言語のビルドコマンドを抑制するために使います(たとえばPythonやJavaScript/TypeScript)。
--source-rootリポジトリのチェックアウト ルートの外部で CLI を実行する場合に使用します。 既定では、database create コマンドで現在のディレクトリがソース ファイルのルート ディレクトリであると見なされます。別の場所を指定するためにこのオプションを使用します。
--codescanning-config[詳細設定]。 CodeQL データベースの作成方法と、後の手順で実行するクエリを指定する構成ファイルがある場合に使用します。 詳細については、「コード スキャン用の高度なセットアップのカスタマイズ」および「database create」を参照してください。

エクストラクターのオプションを指定して、CodeQL データベースを作成するエクストラクターの動作をカスタマイズできます。 詳しくは、「エクストラクターのオプション」を参照してください。

データベースを作成するときに使うことができるすべてのオプションについて詳しくは、「database create」をご覧ください。

単一言語の例

この例では、/checkouts/example-repo でチェックアウトされたリポジトリに対して単一の CodeQL データベースを作成します。 JavaScript 抽出機能を使用して、リポジトリに JavaScript および TypeScript コードの階層表現を作成します。 結果のデータベースは /codeql-dbs/example-repo に格納されます。

$ codeql database create /codeql-dbs/example-repo --language=javascript \
    --source-root /checkouts/example-repo

> Initializing database at /codeql-dbs/example-repo.
> Running command [/codeql-home/codeql/javascript/tools/autobuild.cmd]
    in /checkouts/example-repo.
> [build-stdout] Single-threaded extraction.
> [build-stdout] Extracting
...
> Finalizing database at /codeql-dbs/example-repo.
> Successfully created database at /codeql-dbs/example-repo.

複数言語の例

この例では、/checkouts/example-repo-multi でチェックアウトされたリポジトリの CodeQL データベースを 2 つ作成します。 イベント プロセッサで使用されるものは次のとおりです。

  • --db-cluster: 複数の言語の分析を要求します。
  • --language: データベースを作成する言語を指定します。
  • --command: コードベースのビルド コマンド (ここでは make) をツールに伝えます。
  • --no-run-unnecessary-builds: 必要のない言語 (Python など) のビルド コマンドをスキップするようにツールに伝えます。

結果のデータベースは、/codeql-dbs/example-repo-multipython および cpp サブディレクトリに格納されます。

$ codeql database create /codeql-dbs/example-repo-multi \
    --db-cluster --language python,cpp \
    --command make --no-run-unnecessary-builds \
    --source-root /checkouts/example-repo-multi
Initializing databases at /codeql-dbs/example-repo-multi.
Running build command: [make]
[build-stdout] Calling python3 /codeql-bundle/codeql/python/tools/get_venv_lib.py
[build-stdout] Calling python3 -S /codeql-bundle/codeql/python/tools/python_tracer.py -v -z all -c /codeql-dbs/example-repo-multi/python/working/trap_cache -p ERROR: 'pip' not installed.
[build-stdout] /usr/local/lib/python3.6/dist-packages -R /checkouts/example-repo-multi
[build-stdout] [INFO] Python version 3.6.9
[build-stdout] [INFO] Python extractor version 5.16
[build-stdout] [INFO] [2] Extracted file /checkouts/example-repo-multi/hello.py in 5ms
[build-stdout] [INFO] Processed 1 modules in 0.15s
[build-stdout] <output from calling 'make' to build the C/C++ code>
Finalizing databases at /codeql-dbs/example-repo-multi.
Successfully created databases at /codeql-dbs/example-repo-multi.
$

進行状況と結果

指定したオプションに問題がある場合は、エラーが報告されます。 インタープリター言語の場合、Java に --build-mode none を指定すると、抽出の進行状況がコンソールに表示されます。 ソース ファイルごとに、抽出の成功または失敗がコンソールに表示されます。 コンパイル型言語がビルドされると、コンソールにビルド システムの出力が表示されます。

データベースが正常に作成されると、コマンドで指定したパスに新しいディレクトリが見つかります。 --db-cluster オプションを使用して複数のデータベースを作成した場合は、言語ごとにサブディレクトリが作成されます。 各 CodeQL データベース ディレクトリには、リレーショナル データ (分析に必要) やソース アーカイブ (データベースの作成時に作られたソース ファイルのコピー) などの複数のサブディレクトリが含まれており、分析結果の表示に使用されます。

非コンパイル型言語のデータベースの作成

CodeQL CLI には、非コンパイル型言語 (具体的には JavaScript (および TypeScript)、Python、Ruby) のデータベースを作成するためのエクストラクターが含まれています。 こうしたエクストラクターは、database create を実行するときに --language オプションとして JavaScript、Python、または Ruby を指定すると、自動的に呼び出されます。 これらの言語のデータベースを作成するときは、追加の依存関係がすべて使用可能であることを確認する必要があります。

Note

JavaScript、TypeScript、Python、Ruby 用に database create を実行する場合は、--command オプションを指定しないでください。 そうでないと、通常のエクストラクター呼び出しがオーバーライドされ、空のデータベースが作成されます。 複数の言語のデータベースを作成し、そのうちの 1 つがコンパイル型言語である場合は、--no-run-unnecessary-builds オプションを使用して、コンパイルする必要のない言語のコマンドをスキップします。

JavaScript および TypeScript

JavaScript のデータベースを作成するために追加の依存関係は必要ありませんが、プロジェクトに TypeScript ファイルが含まれている場合は、Node.js 14 以降をインストールして、PATHnode として利用できるようにする必要があります。 コマンド ラインで --language=javascript を指定して、JavaScript と TypeScript の両方のファイルを抽出できます。

codeql database create --language=javascript --source-root <folder-to-extract> <output-folder>/javascript-database

ここでは、--source-root パスを指定しています。これはデータベースの作成が実行される場所ですが、必ずしもコードベースのチェックアウト ルートではありません。

既定では、node_modules および bower_components ディレクトリ内のファイルは抽出されません。

Python

Python のデータベースを作成する場合は、次のことを確認する必要があります。

  • Python 3 がインストールされていて、CodeQL エクストラクターで使用できること。
  • コードで使用している Python のバージョンがインストールされていること。

コマンド ラインで --language=python を指定する必要があります。 次に例を示します。

codeql database create --language=python <output-folder>/python-database

これにより、コードのチェックアウト ルートから database create サブコマンドが実行され、<output-folder>/python-database に新しい Python データベースが生成されます。

Ruby

Ruby のデータベースを作成するには、追加の依存関係は必要ありません。 コマンド ラインで --language=ruby を指定する必要があります。 次に例を示します。

codeql database create --language=ruby --source-root <folder-to-extract> <output-folder>/ruby-database

ここでは、--source-root パスを指定しています。これはデータベースの作成が実行される場所ですが、必ずしもコードベースのチェックアウト ルートではありません。

コンパイル型言語のデータベースの作成

コンパイル型言語では、CodeQL からデータベースを生成するために必要なビルド システムを呼び出す必要があるため、CLI でビルド メソッドを使用できる必要があります。 この方法では、生成されたコードを含むデータベースが作成されます。 CodeQL には、コードベースを構築するには以下の 2 つの方法があります。

ビルド システムの自動検出

CodeQL CLI には、C/C++、C#、Go、Java、Kotlin、および Swift コード用の自動ビルダーが含まれています。 CodeQL の自動ビルダーを使用すると、ビルド コマンドを指定せずにコンパイル型言語のプロジェクトをビルドできます。 自動ビルダーが呼び出されると、CodeQL はソースでビルド システムの証拠を調べ、データベースの抽出に必要な最適なコマンドのセットを実行しようとします。 詳しくは、「コンパイル済み言語の CodeQL コード スキャン」を参照してください。

--command オプションを含めない場合、、コンパイル型言語に対して codeql database create を実行すると、自動ビルダーが自動的に呼び出されます。 たとえば、C/C++ コードベースの場合は、次を実行するだけです。

codeql database create --language=cpp <output-folder>/cpp-database

コードベースで標準のビルド システムを使用するのであれば、多くの場合、自動ビルダーを利用することがデータベースを作成する最も簡単な方法です。 標準以外のビルド ステップを必要とするソースについては、コマンド ラインで各ステップを明示的に定義することが必要な場合があります。

Note

  • Go データベースを構築する場合は、Go ツールチェーン (バージョン 1.11 以降) をインストールし、依存関係がある場合は、適切な依存関係マネージャー (dep など) をインストールします。
  • Go の自動ビルダーはリポジトリ内で、Go で記述されたコードの自動検出を試み、依存関係のフェッチを試みる際にのみビルド スクリプトを実行します。 CodeQL で強制的に、抽出をビルド スクリプトによってコンパイルされたファイルに制限するには、環境変数 CODEQL_EXTRACTOR_GO_BUILD_TRACING=on を設定するか、--command オプションを使用してビルド コマンドを指定します。

ビルド コマンドの指定

次の例は、コンパイル型言語について指定できるビルド コマンドの一部を示すために設計されています。

Note

--command オプションで指定できる引数は 1 つです。複数のコマンドを使用する必要がある場合は、--command を複数回指定します。 サブコマンドとオプションを渡す必要がある場合は、正しく解釈されるように引数全体を引用符で囲む必要があります。

  • make を使用してビルドされた C/C++ プロジェクト:

    codeql database create cpp-database --language=cpp --command=make
    
  • dotnet build を使用してビルドされた C# プロジェクト:

    すべてのコードが確実にビルドされるように /t:rebuild を追加するか、事前に dotnet clean を実行することをお勧めします (ビルドされていないコードは CodeQL データベースに含まれません)。

    codeql database create csharp-database --language=csharp --command='dotnet build /t:rebuild'
    
  • CODEQL_EXTRACTOR_GO_BUILD_TRACING=on 環境変数を使用してビルドされた Go プロジェクト:

    CODEQL_EXTRACTOR_GO_BUILD_TRACING=on codeql database create go-database --language=go
    
  • カスタム ビルド スクリプトを使用してビルドされた Go プロジェクト:

    codeql database create go-database --language=go --command='./scripts/build.sh'
    
  • Gradle を使用してビルドされた Java プロジェクト:

    # Use `--no-daemon` because a build delegated to an existing daemon cannot be detected by CodeQL.
    # To ensure isolated builds without caching, add `--no-build-cache` on persistent machines.
    codeql database create java-database --language=java --command='gradle --no-daemon clean test'
    
  • Maven を使用してビルドされた Java プロジェクト:

    codeql database create java-database --language=java --command='mvn clean install'
    
  • Ant を使用してビルドされた Java プロジェクト:

    codeql database create java-database --language=java --command='ant -f build.xml'
    
  • Xcode プロジェクトまたはワークスペースからビルドされた Swift プロジェクト。 既定では、最大の Swift ターゲットがビルドされます。

    プロジェクトがクリーン状態であり、使用可能なビルドアーティファクトがないことを確認するのは良い考えです。

    xcodebuild clean -all
    codeql database create -l swift swift-database
    
  • swift build を使用してビルドされた Swift プロジェクト:

    codeql database create -l swift -c "swift build" swift-database
    
  • xcodebuild を使用してビルドされた Swift プロジェクト:

    codeql database create -l swift -c "xcodebuild build -target your-target" swift-database
    

    archivetest オプションを xcodebuild に渡すことができます。 ただし、標準の xcodebuild コマンドが推奨されます。これは最も速く、CodeQL のスキャンが成功するために必要なものがすべて揃っているはずです。

  • カスタム ビルド スクリプトを使用してビルドされた Swift プロジェクト:

    codeql database create -l swift -c "./scripts/build.sh" swift-database
    
  • Bazel を使用してビルドされたプロジェクト:

    # Navigate to the Bazel workspace.
    
    # Before building, remove cached objects
    # and stop all running Bazel server processes.
    bazel clean --expunge
    
    # Build using the following Bazel flags, to help CodeQL detect the build:
    # `--spawn_strategy=local`: build locally, instead of using a distributed build
    # `--nouse_action_cache`: turn off build caching, which might prevent recompilation of source code
    # `--noremote_accept_cached`, `--noremote_upload_local_results`: avoid using a remote cache
    # `--disk_cache=`: avoid using a disk cache. Note that a disk cache is no longer considered a remote cache as of Bazel 6.
    codeql database create new-database --language=<language> \
    --command='bazel build --spawn_strategy=local --nouse_action_cache --noremote_accept_cached --noremote_upload_local_results --disk_cache= //path/to/package:target'
    
    # After building, stop all running Bazel server processes.
    # This ensures future build commands start in a clean Bazel server process
    # without CodeQL attached.
    bazel shutdown
    
  • カスタム ビルド スクリプトを使用してビルドされたプロジェクト:

    codeql database create new-database --language=<language> --command='./scripts/build.sh'
    

このコマンドにより、プロジェクトのビルドに必要なすべてのコマンドを含むカスタム スクリプトを実行します。

間接ビルド トレースの使用

コンパイル型言語の CodeQL CLI 自動ビルダーが CI ワークフローで動作せず、codeql database trace-command でビルド コマンドの呼び出しをラップできない場合は、間接ビルド トレースを使用して CodeQL データベースを作成できます。 間接ビルド トレースを使用するには、CI システムで各ビルド アクションのカスタム環境変数を設定できる必要があります。

間接ビルド トレースを使用して CodeQL データベースを作成するには、プロジェクトのチェックアウト ルートから次のコマンドを実行します。

codeql database init ... --begin-tracing <database>

ユーザーは次のものを指定する必要があります。

  • <database>: 作成する新しいデータベースへのパス。 このコマンドを実行すると、このディレクトリが作成されます。既存のディレクトリを指定することはできません。
  • --begin-tracing: ビルド コマンドがトレースされる環境を設定するために使用できるスクリプトを作成します。

codeql database init コマンドの他のオプションを通常どおり指定できます。

Note

Windows でビルドを実行する場合は、--trace-process-level <number> または --trace-process-name <parent process name> を設定して、分析対象コードのすべてのビルド ステップを監視する親 CI プロセスをオプションで参照する必要があります。

codeql database init コマンドによりメッセージが出力されます。

Created skeleton <database>. This in-progress database is ready to be populated by an extractor. In order to initialise tracing, some environment variables need to be set in the shell your build will run in. A number of scripts to do this have been created in <database>/temp/tracingEnvironment. Please run one of these scripts before invoking your build command.

Based on your operating system, we recommend you run: ...

codeql database init コマンドを使用すると、CodeQL で一連のビルド ステップをトレースできるようにするための環境変数と値が含まれたファイルと共に、<database>/temp/tracingEnvironment が作成されます。 これらのファイルには start-tracing.{json,sh,bat,ps1} のように名前が付けられます。 これらのファイルの 1 つを CI システムのメカニズムと共に使用して、今後の手順のための環境変数を設定します。 次のようにすることができます。

  • JSON ファイルを読み取り、処理し、CI システムによって想定されている形式で環境変数を出力します。 たとえば、Azure DevOps では echo "##vso[task.setvariable variable=NAME]VALUE" が想定されています。
  • または、CI システムで環境を永続化する場合は、適切な start-tracing スクリプトをソースとして、CI システムのシェル環境に CodeQL 変数を設定します。

コードをビルドします。必要に応じて、start-tracing スクリプトが保存されているディレクトリにある end-tracing.{json,sh,bat,ps1} スクリプトを使用して環境変数の設定を解除してから、codeql database finalize <database> コマンドを実行します。

間接ビルド トレースを使用して CodeQL データベースを作成したら、それを他の CodeQL データベースと同様に操作できます。 たとえば、データベースを分析し、コード スキャンを使用する場合は GitHub に結果をアップロードします。

間接ビルド トレースを使用して CodeQL データベースを作成する例

Note

Azure DevOps パイプラインを使用する場合、CodeQL データベースを作成する最も簡単な方法は、GitHub Advanced Security for Azure DevOps を使用することです。 ドキュメントについては、Microsoft Learn で「GitHub Advanced Security for Azure DevOps を構成する」を参照してください。

次の例は、Azure DevOps パイプラインでの間接ビルド トレースを使用して CodeQL データベースを作成する方法を示しています。

steps:
    # Download the CodeQL CLI and query packs...
    # Check out the repository ...

    # Run any pre-build tasks, for example, restore NuGet dependencies...

    # Initialize the CodeQL database.
    # In this example, the CodeQL CLI has been downloaded and placed on the PATH.
    - task: CmdLine@1
       displayName: Initialize CodeQL database
      inputs:
          # Assumes the source code is checked out to the current working directory.
          # Creates a database at `<current working directory>/db`.
          # Running on Windows, so specifies a trace process level.
          script: "codeql database init --language csharp --trace-process-name Agent.Worker.exe --source-root . --begin-tracing db"

    # Read the generated environment variables and values,
    # and set them so they are available for subsequent commands
    # in the build pipeline. This is done in PowerShell in this example.
    - task: PowerShell@1
       displayName: Set CodeQL environment variables
       inputs:
          targetType: inline
          script: >
             $json = Get-Content $(System.DefaultWorkingDirectory)/db/temp/tracingEnvironment/start-tracing.json | ConvertFrom-Json
             $json.PSObject.Properties | ForEach-Object {
                 $template = "##vso[task.setvariable variable="
                 $template += $_.Name
                 $template += "]"
                 $template += $_.Value
                 echo "$template"
             }

    # Execute the pre-defined build step. Note the `msbuildArgs` variable.
    - task: VSBuild@1
        inputs:
          solution: '**/*.sln'
          msbuildArgs: /p:OutDir=$(Build.ArtifactStagingDirectory)
          platform: Any CPU
          configuration: Release
          # Execute a clean build, in order to remove any existing build artifacts prior to the build.
          clean: True
       displayName: Visual Studio Build

    # Read and set the generated environment variables to end build tracing. This is done in PowerShell in this example.
    - task: PowerShell@1
       displayName: Clear CodeQL environment variables
       inputs:
          targetType: inline
          script: >
             $json = Get-Content $(System.DefaultWorkingDirectory)/db/temp/tracingEnvironment/end-tracing.json | ConvertFrom-Json
             $json.PSObject.Properties | ForEach-Object {
                 $template = "##vso[task.setvariable variable="
                 $template += $_.Name
                 $template += "]"
                 $template += $_.Value
                 echo "$template"
             }

    - task: CmdLine@2
       displayName: Finalize CodeQL database
       inputs:
          script: 'codeql database finalize db'

    # Other tasks go here, for example:
    # `codeql database analyze`
    # then `codeql github upload-results` ...

次のステップ