Skip to main content

CodeQL クエリ スイートの作成

CodeQL分析で頻繁に使用するクエリのクエリ スイートを作成できます。

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

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

  • GitHub.com のパブリック リポジトリについては、「GitHub CodeQL の使用条件」を参照してください
  • GitHub Team が有効になっている GitHub Enterprise Cloud または GitHub Code Security 上の organization 所有のリポジトリ

CodeQL分析で頻繁に使用するクエリのクエリ スイートを作成できます。 詳細については、「CodeQL クエリ セット」を参照してください。

メモ

クエリ スイートに追加するカスタム クエリは、 CodeQL パック 内にあり、正しいクエリ メタデータが含まれている必要があります。 詳細については、「CodeQL CLI のカスタム クエリの記述」を参照してください。

クエリ スイートに追加するクエリの場所指定

クエリ スイートを作成するときは、選びたいクエリの場所を最初に指定する必要があります。 次を使用して、1 つ以上のクエリの場所を定義できます。

  • query命令: 指定した 1 つ以上のCodeQL ファイルを検索するように.qlに指示します。

    - query: <path-to-query>
    

    引数は、スイート定義を含む CodeQL パックを基準にした 1 つ以上のファイル パスである必要があります。

  • queries命令: CodeQL ファイルのディレクトリを再帰的にスキャンするように.qlに指示します。

    - queries: <path-to-subdirectory>
    

    ディレクトリのパスは、スイート定義ファイルを含む CodeQL パックのルートを基準とする相対パスである必要があります。 別の CodeQL パックに対するクエリを検索するには、 from フィールドを追加します。

    - queries: <path-to-subdirectory>
      from: <ql-pack-name>
      version: ^x.y.z
    

version フィールドは省略可能であり、このCodeQL パックの互換性のあるバージョンの範囲を指定します。 バージョンを指定しない場合は、パックの最新バージョンが使用されます。

  • qlpack命令: 名前付き CodeQL パックの既定のスイートでクエリを解決するようにCodeQLに指示します。

    - qlpack: <qlpack-name>
      version: ^x.y.z
    

    クエリ パックの既定のスイートには、そのクエリ パック内で推奨されるクエリのセットが含まれています。 すべてのクエリ パックに既定のスイートがあるわけではありません。 指定されたクエリ パックで既定のスイートが定義されていない場合、qlpack 命令はパック内のすべてのクエリに解決されます。

version フィールドは省略可能であり、このCodeQL パックの互換性のあるバージョンの範囲を指定します。 バージョンを指定しない場合は、パックの最新バージョンが使用されます。

メモ

パス名がクエリ スイート定義に表示される場合は、常にスラッシュ / をディレクトリ区切りとして指定する必要があります。 これにより、クエリ スイート定義がすべてのオペレーティング システムで確実に機能します。

スイート定義には少なくとも 1 つの queryqueries、または qlpack 命令を追加する必要があります。それ以外の場合、クエリは選ばれません。 スイートにそれ以上の指示が含まれていない場合は、ファイル一覧、指定されたディレクトリ、または指定された名前の CodeQL パック内で見つかったすべてのクエリが選択されます。 さらにフィルター処理命令がある場合は、それらの命令によって課される制約に一致するクエリのみが選ばれます。

クエリ スイートでのクエリのフィルター処理

queryqueries、または qlpack 命令を指定してスイートに追加するクエリの初期セットを定義した後、includeexclude の命令を追加できます。 次の命令では、特定のプロパティに基づいて選択条件が定義されます。

  • クエリのセットに対して include 命令を実行すると、条件に一致するすべてのクエリが選択に保持され、一致しないクエリは削除されます。
  • クエリのセットに対して exclude 命令を実行すると、条件に一致するすべてのクエリが選択から削除され、一致しないクエリは保持されます。

フィルター命令の順序は重要です。 命令の場所指定後に表示される最初のフィルター命令によって、既定でクエリを含めるか除外するかが決まります。 最初のフィルターが include、最初に場所指定されたクエリは、明示的な include フィルターと一致する場合にのみスイートの一部になります。 最初のフィルターが exclude、最初に場所指定されたクエリは、明示的に除外されている場合にのみスイートの一部になります。

後続の命令は順番に実行され、ファイル内で後にある命令の方が前にある命令よりも優先されます。 そのため、include 命令は、同じクエリに一致する後の exclude 命令によってオーバーライドできます。 同様に、exclude は後の includeによってオーバーライドできます。

どちらの命令でも、引数は制約ブロックです。つまり、制約を表す YAML マップです。 各制約はマップ エントリであり、この場合のキーは通常、クエリ メタデータ プロパティです。 次の値が考えられます。

  • 1 つの文字列。
  • / で囲まれた正規表現
  • 文字列、正規表現、またはその両方を含むリスト。

制約に一致させるには、メタデータ値が文字列または正規表現のいずれかに一致する必要があります。 複数のメタデータ キーがある場合は、各キーを一致させる必要があります。 照合に使用できる標準メタデータ キーは descriptionidkindnametagsprecision、および problem.severity です。 クエリ メタデータ プロパティの詳細については、「CodeQL クエリのメタデータ」を参照してください。

メタデータ タグに加えて、制約ブロック内のキーは次の場合もあります。

  • query filename: クエリ ファイル名の最後のパス コンポーネントと一致します。
  • query path: それを含む CodeQL パックからのクエリ ファイルへの相対パスに一致します。
  • tags contain: 指定された照合文字列の 1 つが、@tags メタデータ プロパティの値のスペース区切りコンポーネントのいずれかに一致する必要があります。
  • tags contain all: 指定されたそれぞれの照合文字列が、@tags メタデータ プロパティのコンポーネントのいずれかに一致する必要があります。

実行するクエリのフィルター処理の例

一般的なユース ケースは、ユーザーが実行したくない特定のクエリを除き、 CodeQL パック内のすべてのクエリを実行するクエリ スイートを作成することです。 一般的には、クエリごとに一意で安定した識別子であるクエリ id でフィルター処理することをお勧めします。 次の 3 つのクエリ スイート定義は、意味的に同一であり、クエリ id でフィルター処理されます。

このフィルターは、除外された識別子を持つ 2 つのクエリを除き、codeql/cpp-queries の既定のスイート内のすべてのクエリと一致します。

- qlpack: codeql/cpp-queries
- exclude:
    id:
      - cpp/cleartext-transmission
      - cpp/cleartext-storage-file

この例では、クエリごとに個別の exclude 命令が使用されます。

- qlpack: codeql/cpp-queries
- exclude:
    id: cpp/cleartext-transmission
- exclude:
    id: cpp/cleartext-storage-file

この例では、正規表現によって同じ 2 つのクエリが除外されます。 また、cpp/cleartext- で始まる識別子を持つスイートに追加される今後のクエリも除外されます。

- qlpack: codeql/cpp-queries
- exclude:
    id:
      - /^cpp\/cleartext-.*/

codeql/cpp-queries CodeQL パックの既定のスイート内のすべてのクエリを選択し、セキュリティ クエリのみを含むように絞り込むスイートを定義するには、次の値を使用します。

- qlpack: codeql/cpp-queries
- include:
    tags contain: security

@kind problem ディレクトリから @precision highmy-custom-queries のすべてのクエリが選ばれるスイートを定義するには、次を使用します。

- queries: my-custom-queries
- include:
    kind: problem
    precision: very-high

次のクエリ スイート定義は、上記の定義とは異なる動作をします。 この定義では、@kind problem_ または_@precision very-high であるクエリを選択します。

- queries: my-custom-queries
- include:
    kind: problem
- include:
    precision: very-high

@kind problem を含むものを除き、my-custom-queries ディレクトリから @problem.severity recommendation のすべてのクエリが選ばれるスイートを作成するには、次を使用します。

- queries: my-custom-queries
- include:
    kind: problem
- exclude:
    problem.severity: recommendation

@tag security @precision high パックからvery-highおよびcodeql/cpp-queriesまたはCodeQLを含むすべてのクエリを選択するスイートを作成するには、次の値を使用します。

- queries: .
  from: codeql/cpp-queries
- include:
    tags contain: security
    precision:
    - high
    - very-high

メモ

codeql resolve queries /path/to/suite.qls コマンドを使用すると、クエリ スイート定義で選ばれているクエリを確認できます。 詳細については、「クエリを解決する」を参照してください。

既存のクエリ スイート定義の再利用

既存のクエリ スイート定義は、次を指定することで再利用できます。

  • import 命令: 以前に定義した .qls ファイルによって選ばれたクエリを現在のスイートに追加します。

    - import: <path-to-query-suite>
    

    インポートされたスイートへのパスは、現在のスイート定義を含む CodeQL パックに対する相対パスである必要があります。 インポートされたクエリ スイートが別の QL パックにある場合は、次を使用できます。

    - import: <path-to-query-suite>
      from: <ql-pack>
      version: ^x.y.z
    

version フィールドは省略可能であり、このCodeQL パックの互換性のあるバージョンの範囲を指定します。 バージョンを指定しない場合は、パックの最新バージョンが使用されます。

import 命令を使用して追加されたクエリは、後続の exclude 命令を使用してフィルター処理できます。

  • apply 命令: 以前に定義した .qls ファイルのすべての命令を現在のスイートに追加します。 適用された .qls ファイル内の命令が、apply の代わりに表示されたかのようにして実行されます。 適用されたスイートの includeexclude の命令は、以前の命令によって追加されたクエリにも作用します。

    - apply: <path-to-query-suite>
    

apply 命令を使用して、.yml ファイルに保存された一連の再利用可能な条件を複数のクエリ定義に適用することもできます。 詳しくは、下記のをご覧ください。

再利用性の例

複数のクエリ スイート定義で同じ条件を使用するには、命令を含む別の .yml ファイルを作成します。 たとえば、reusable-instructions.yml という名前のファイルに次を保存します。

- include:
    kind:
    - problem
    - path-problem
    tags contain: security
    precision:
    - high
    - very-high

現在のクエリ スイートと同じreusable-instructions.yml パックにCodeQLを追加します。 次に、1 つ以上のクエリ スイートで、apply 命令を使用して、再利用可能な命令を現在のスイートに適用します。 例えば次が挙げられます。

- queries: queries/cpp/custom
- apply: reusable-instructions.yml

これにより、queries/cpp/custom のクエリがフィルター処理され、再利用可能な条件に一致するもののみが含まれるようになります。

また、別のreusable-instructions.yml パック内のクエリに対してCodeQLを使用してスイート定義を作成することもできます。 .qls ファイルがクエリと同じCodeQL パック内にある場合は、from命令の直後にapply フィールドを追加できます。

# load queries from the default suite of my-org/my-other-custom-queries
- qlpack: my-org/my-other-custom-queries

# apply the reusable instructions from the my-org/my-custom-instructions CodeQL pack
- apply: reusable-instructions.yml
  from: my-org/my-custom-instructions
  version: ^1.2.3 # optional

import 命令の一般的なユース ケースは、別のクエリ スイートのクエリにさらにフィルターを適用することです。 たとえば、このスイートでは、cpp-security-and-quality スイートをさらにフィルター処理し、lowmedium の有効桁数クエリが除外されます。

- import: codeql-suites/cpp-security-and-quality.qls
  from: codeql/cpp-queries
- exclude:
    precision:
      - low
      - medium

別のスイートからインポートされたクエリを include する場合、構文は少し異なります。

- import: codeql-suites/cpp-security-and-quality.qls
  from: codeql/cpp-queries
- exclude: {}
- include:
    precision:
      - very-high
      - high

空の exclude 命令に注目してください。 これは、後続の include 命令がインポートされたスイートからのクエリをフィルター処理できるようにするために必要です。

クエリ スイートの名前付け

クエリ スイートの名前を指定するには、description 命令を指定します。

- description: <name-of-query-suite>

クエリ スイートの保存

.qls 拡張子のファイルにクエリスイートを保存し、それを CodeQL に追加します パック。 詳細については、「CodeQL パックを使った分析のカスタマイズ」を参照してください。

CodeQL でクエリ スイートを使用する

.qls ファイルを受け入れるコマンドに対して、コマンド ラインでクエリ スイートを指定できます。 たとえば、query compile を使用してスイート定義によって選ばれたクエリをコンパイルしたり、database analyze を使用して分析でクエリを使用したりできます。 CodeQL データベースの分析の詳細については、AUTOTITLE を参照してください。

詳細については、次を参照してください。