Skip to main content

Création de suites de requêtes CodeQL

Vous pouvez créer des suites de requêtes pour les requêtes que vous utilisez fréquemment dans vos analyses CodeQL.

Qui peut utiliser cette fonctionnalité ?

GitHub CodeQL est concédé sous licence par utilisateur lors de l’installation. Vous pouvez utiliser CodeQL uniquement pour certaines tâches soumises aux restrictions de licence. Pour plus d’informations, consultez « À propos de CodeQL CLI ».

Si vous disposez d’une licence GitHub Advanced Security, vous pouvez utiliser CodeQL pour l’analyse automatisée, l’intégration continue et la livraison continue. Pour plus d’informations, consultez « À propos de GitHub Advanced Security ».

À propos de la création de suites de requêtes CodeQL

Les suites de requêtes CodeQL permettent de sélectionner des requêtes, en fonction de leur nom de fichier, de leur emplacement sur le disque ou dans un pack CodeQL , ou de propriétés des métadonnées. Créez des suites de requêtes pour les requêtes que vous voulez utiliser fréquemment dans vos analyses CodeQL.

Les suites de requêtes vous permettent de passer plusieurs requêtes à CodeQL sans devoir spécifier individuellement le chemin de chaque fichier de requête. Les définitions de suite de requêtes sont stockées dans des fichiers YAML avec l’extension .qls. Une définition de suite est une séquence d’instructions, où chaque instruction est un mappage YAML avec (en général) une clé unique. Les instructions sont exécutées dans l’ordre dans lequel elles apparaissent dans la définition de la suite de requêtes. Une fois que toutes les instructions de la définition de la suite ont été exécutées, le résultat est un ensemble de requêtes sélectionnées.

Remarque : Les requêtes personnalisées que vous voulez ajouter à une suite de requêtes doivent se trouver dans un pack CodeQL et contenir les métadonnées de requête correctes. Pour plus d’informations, consultez « Utilisation de requêtes personnalisées avec CodeQL CLI ».

Localisation des requêtes à ajouter à une suite de requêtes

Lors de la création d’une suite de requêtes, vous devez d’abord spécifier les emplacements des requêtes que vous voulez sélectionner. Vous pouvez définir l’emplacement d’une ou plusieurs requêtes en utilisant :

  • Une instruction query - indique à CodeQL de rechercher un ou plusieurs fichiers .ql spécifiés :

    - query: <path-to-query>
    

    L’argument doit être un ou plusieurs chemins de fichier, relativement au pack CodeQL contenant la définition de la suite.

  • Une instruction queries - indique à CodeQL de parcourir un répertoire de façon récursive pour y rechercher des fichiers .ql :

    - queries: <path-to-subdirectory>
    

    Le chemin du répertoire doit être relatif à la racine du pack CodeQL qui contient le fichier de définition de la suite. Pour rechercher les requêtes relatives à un autre pack CodeQL, ajoutez un champ from :

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

    Le champ version est facultatif et spécifie une plage de versions compatibles de ce pack CodeQL. Si vous ne spécifiez pas de version, la version la plus récente du pack est utilisée.

  • Une instruction qlpack - indique à CodeQL de résoudre les requêtes dans la suite par défaut du pack CodeQL nommé :

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

    La suite par défaut d’un pack de requêtes comprend un ensemble recommandé de requêtes au sein de ce pack de requêtes. Tous les packs de requêtes n’ont pas une suite par défaut. Si le pack de requêtes donné ne définit pas de suite par défaut, l’instruction qlpack va avoir comme résultat toutes les requêtes du pack.

    Le champ version est facultatif et spécifie une plage de versions compatibles de ce pack CodeQL. Si vous ne spécifiez pas de version, la version la plus récente du pack est utilisée.

Remarque : Quand des noms de chemin apparaissent dans les définitions d’une suite de requêtes, ils doivent toujours être indiqués avec une barre oblique / comme séparateur de répertoires. Ceci garantit que les définitions de suite de requêtes fonctionnent sur tous les systèmes d’exploitation.

Vous devez ajouter au moins une instruction query, queries ou qlpack à votre définition de suite, sinon aucune requête ne sera sélectionnée. Si la suite ne contient pas d’autres instructions, toutes les requêtes trouvées dans la liste des fichiers, dans le répertoire donné ou dans le pack CodeQL nommé sont sélectionnées. S’il existe d’autres instructions de filtrage, seules les requêtes qui correspondent aux contraintes imposées par ces instructions seront sélectionnées.

Filtrage des requêtes dans une suite de requêtes

Après avoir défini l’ensemble initial de requêtes à ajouter à votre suite en spécifiant des instructions query, queries ou qlpack, vous pouvez ajouter des instructions include et exclude. Ces instructions définissent des critères de sélection basés sur des propriétés spécifiques :

  • Quand vous exécutez une instruction include sur un ensemble de requêtes, toutes les requêtes qui correspondent à vos conditions sont conservées dans la sélection, et les requêtes qui ne correspondent pas sont retirées.
  • Quand vous exécutez une instruction exclude sur un ensemble de requêtes, toutes les requêtes qui correspondent à vos conditions sont retirées de la sélection et les requêtes qui n’y correspondent pas sont conservées.

L’ordre de vos instructions de filtrage est important. La première instruction de filtrage qui apparaît après les instructions relatives aux emplacements détermine si les requêtes sont incluses ou exclues par défaut. Si le premier filtre est un include, les requêtes initialement sélectionnées sur la base de leur emplacement font partie de la suite seulement si elles correspondent à un filtre include explicite. Si le premier filtre est un exclude, les requêtes initialement sélectionnées sur la base de leur emplacement font partie de la suite à moins d’être explicitement exclues.

Les instructions suivantes sont exécutées dans l’ordre et les instructions qui apparaissent plus tard dans le fichier sont prioritaires sur les instructions précédentes. Ainsi, les instructions include peuvent être remplacées par des instructions exclude ultérieures qui correspondent à la même requête. De même, des instructions exclude peuvent être remplacées par une instruction include ultérieure.

Pour les deux instructions, l’argument est un bloc de contraintes, c’est-à-dire un mappage YAML représentant les contraintes. Chaque contrainte est une entrée de mappage, où la clé est généralement une propriété de métadonnées de requête. La valeur peut être :

  • Une seule chaîne.
  • Une expression régulière entre des /.
  • Une liste contenant des chaînes, des expressions régulières ou les deux.

Pour correspondre à une contrainte, une valeur de métadonnées doit correspondre à une des chaînes ou des expressions régulières. Quand il existe plusieurs clés de métadonnées, chaque clé doit correspondre. Les clés de métadonnées standard disponibles pour la mise en correspondance sont : description, id, kind, name, tags, precision et problem.severity. Pour plus d’informations sur les propriétés de métadonnées de requête, consultez « Métadonnées pour les requêtes CodeQL ».

En plus des étiquettes de métadonnées, les clés du bloc de contraintes peuvent également être :

  • query filename - correspond au dernier composant du chemin du nom de fichier de la requête.
  • query path - correspond au chemin du fichier de la requête relativement au pack CodeQL qui la contient.
  • tags contain - une des chaînes de correspondance spécifiées doit correspondre à un des composants séparés par un espace de la valeur de la propriété de métadonnées @tags.
  • tags contain all - chacune des chaînes de correspondance spécifiées doit correspondre à un des composants de la propriété de métadonnées @tags.

Exemples de filtrage des requêtes exécutées

Un cas d’usage courant est de créer une suite de requêtes qui exécute toutes les requêtes d’un pack CodeQL, à l’exception de quelques requêtes spécifiques que l’utilisateur ne veut pas exécuter. D’une façon générale, nous vous recommandons de filtrer sur l’id de requête, qui est un identificateur unique et stable pour chaque requête. Les trois définitions de suite de requêtes suivantes sont sémantiquement identiques et filtrent par id de requête :

Ce filtre correspond à toutes les requêtes de la suite par défaut de codeql/cpp-queries, à l’exception des deux requêtes ayant les identificateurs exclus :

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

Dans cet exemple, une instruction exclude distincte est utilisée pour chaque requête :

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

Dans cet exemple, une expression régulière exclut les deux mêmes requêtes. Elle exclut également toutes les requêtes futures ajoutées à la suite avec des identificateurs qui commencent par cpp/cleartext- :

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

Pour définir une suite qui sélectionne toutes les requêtes dans la suite par défaut du pack CodeQL codeql/cpp-queries, puis les affine pour inclure seulement les requêtes de sécurité, utilisez :

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

Pour définir une suite qui sélectionne toutes les requêtes avec @kind problem et @precision high dans le répertoire my-custom-queries, utilisez :

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

Notez que la définition de suite de requêtes suivante se comporte différemment de la définition ci-dessus. Cette définition sélectionne les requêtes qui sont @kind problem ou sont @precision very-high :

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

Pour créer une suite qui sélectionne toutes les requêtes avec @kind problem dans le répertoire my-custom-queries à l’exception de celles avec @problem.severity recommendation, utilisez :

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

Pour créer une suite qui sélectionne toutes les requêtes avec @tag security et @precision high ou very-high dans le pack CodeQL codeql/cpp-queries, utilisez :

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

Remarque : Vous pouvez utiliser la commande codeql resolve queries /path/to/suite.qls pour voir quelles requêtes sont sélectionnées par une définition de suite de requêtes. Pour plus d’informations, consultez « resolve queries ».

Réutilisation de définitions de suite de requêtes existantes

Les définitions de suite de requêtes existantes peuvent être réutilisées en spécifiant :

  • Une instruction import - ajoute les requêtes sélectionnées par un fichier .qls précédemment défini à la suite actuelle :

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

    Le chemin de la suite importée doit être relatif au pack CodeQL contenant la définition actuelle de la suite. Si la suite de requêtes importée se trouve dans un autre pack QL, vous pouvez utiliser :

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

    Le champ version est facultatif et spécifie une plage de versions compatibles de ce pack CodeQL. Si vous ne spécifiez pas de version, la version la plus récente du pack est utilisée.

    Les requêtes ajoutées avec une instruction import peuvent être filtrées en utilisant des instructions exclude ultérieures.

  • Une instruction apply - ajoute toutes les instructions d’un fichier .qls défini précédemment à la suite actuelle. Les instructions du fichier .qls appliqué sont exécutées comme si elles se trouvaient à la place de apply. Les instructions include et exclude de la suite appliquée agissent également sur les requêtes ajoutées par les instructions antérieures :

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

    L’instruction apply peut aussi être utilisée pour appliquer à plusieurs définitions de requête un ensemble de conditions réutilisables, enregistrées dans un fichier .yml. Pour plus d’informations, consultez les exemples ci-dessous.

Exemples de réutilisabilité

Pour utiliser les mêmes conditions dans plusieurs définitions de suite de requêtes, créez un fichier .yml distinct contenant vos instructions. Par exemple, enregistrez ceci dans un fichier appelé reusable-instructions.yml :

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

Ajoutez reusable-instructions.yml au même pack CodeQL que votre suite de requêtes actuelle. Ensuite, dans une ou plusieurs suites de requêtes, utilisez l’instruction apply pour appliquer les instructions réutilisables à la suite active. Par exemple :

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

Ceci filtre les requêtes dans queries/cpp/custom pour inclure seulement celles qui correspondent aux conditions réutilisables.

Vous pouvez aussi créer une définition de suite en utilisant reusable-instructions.yml sur les requêtes d’un autre pack CodeQL. Si le fichier .qls se trouve dans le même pack CodeQL que les requêtes, vous pouvez ajouter un champ from immédiatement après l’instruction 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

Un cas d’usage courant pour une instruction import est d’appliquer un filtre supplémentaire aux requêtes d’une autre suite de requêtes. Par exemple, cette suite va appliquer un filtrage supplémentaire à la suite cpp-security-and-quality, et exclure les requêtes de précision low et medium :

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

Si vous voulez faire un include des requêtes importées depuis une autre suite, la syntaxe est légèrement différente :

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

Notez l’instruction exclude vide. Ceci est nécessaire pour garantir que l’instruction include qui suit est en mesure de filtrer les requêtes de la suite importée.

Nommage d’une suite de requêtes

Vous pouvez fournir un nom pour votre suite de requêtes en spécifiant une instruction description :

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

Enregistrement d’une suite de requêtes

Enregistrez votre suite de requêtes dans un fichier avec une extension .qls et ajoutez-la à un pack CodeQL. Pour plus d’informations, consultez « Personnalisation de l’analyse avec des packs CodeQL ».

Utilisation de suites de requêtes avec CodeQL

Vous pouvez spécifier des suites de requêtes sur la ligne de commande pour les commandes qui acceptent des fichiers .qls. Par exemple, vous pouvez compiler les requêtes sélectionnées par une définition de suite en utilisant query compile ou utiliser les requêtes dans une analyse en utilisant database analyze. Pour plus d’informations sur l’analyse de bases de données CodeQL, consultez « Analyse de votre code avec des requêtes CodeQL ».

Pour aller plus loin