Skip to main content

Préparation de votre code pour l’analyse CodeQL

Vous pouvez créer une base de données CodeQL contenant les données nécessaires pour analyser votre code.

Qui peut utiliser cette fonctionnalité ?

Utilisateurs disposant d’un accès en lecture à un référentiel

CodeQL est disponible pour les types de référentiels suivants :

À propos de la préparation du code pour l’analyse

Avant d’analyser votre code avec CodeQL, vous devez créer une base de données CodeQL contenant toutes les données nécessaires pour exécuter des requêtes sur votre code. Vous pouvez créer vous-même des bases de données CodeQL en utilisant CodeQL CLI.

L’analyse CodeQL repose sur l’extraction de données relationnelles de votre code et sur leur utilisation pour créer une base de données CodeQL. Les bases de données CodeQL contiennent toutes les informations importantes relatives à un codebase, qui peuvent être analysées en exécutant des requêtes CodeQL dessus.

Avant de générer une base de données CodeQL, vous devez :

  1. Installer et configurer CodeQL CLI Pour plus d’informations, consultez « Configuration de CodeQL CLI ».
  2. Extrayez le code à analyser :
    • Pour une branche, extrayez la tête (début) de la branche à analyser.
    • Pour une demande de tirage, extrayez son commit de tête ou un commit de fusion généré par GitHub.
  3. Configurez l’environnement pour le codebase, en vérifiant que toutes les dépendances sont disponibles.
  4. Pour obtenir les meilleurs résultats avec des langages compilés, recherchez la commande de génération, le cas échéant, pour la codebase. En général, celle-ci est disponible dans un fichier de configuration dans le système CI.

Une fois le codebase prêt, vous pouvez exécuter codeql database create pour créer la base de données. Pour plus d’informations, consultez « Création de bases de données pour les langages non compilés » et « Création de bases de données pour les langages compilés ».

En cours d’exécution codeql database create

Les bases de données CodeQL sont créées en exécutant la commande suivante à partir de la racine d’extraction de votre projet :

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

Vous devez spécifier :

  • <database> : chemin de la nouvelle base de données à créer. Ce répertoire est créé lorsque vous exécutez la commande. Vous ne pouvez pas spécifier de répertoire existant.

  • --language : identificateur du langage pour lequel créer une base de données. Utilisée avec --db-cluster, l’option accepte une liste séparée par des virgules ou peut être spécifiée plusieurs fois. CodeQL prend en charge la création de bases de données pour les langages suivants :

    LangageIdentificateurIdentificateurs alternatifs facultatifs (le cas échéant)
    C/C++c-cppc ou cpp
    C#csharp
    Gogo
    Java/Kotlinjava-kotlinjava ou kotlin
    JavaScript/TypeScriptjavascript-typescriptjavascript ou typescript
    Pythonpython
    Rubyruby
    Swiftswift

    Remarque : Si vous spécifiez l’un des autres identificateurs, cette action équivaut à utiliser l’identificateur de langage standard. Par exemple, la spécification javascript au lieu de javascript-typescript n’exclut pas l’analyse du code TypeScript. Vous pouvez le faire dans un flux de travail d’installation avancé avec l’option --paths-ignore. Pour plus d’informations, consultez « Personnalisation de votre configuration avancée pour l’analyse de code ».

Si votre codebase dispose d'une commande ou d'un script de construction qui invoque le processus de construction, nous vous recommandons de le spécifier également :

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

Options de création de bases de données

Vous pouvez spécifier des options supplémentaires en fonction de l’emplacement de votre fichier source, si le code doit être compilé et si vous voulez créer des bases de données CodeQL pour plusieurs langages.

OptionObligatoireUsage
<database>Spécifiez le nom et l’emplacement d’un répertoire à créer pour la base de données CodeQL. La commande échoue si vous essayez de remplacer un répertoire existant. Si vous spécifiez aussi --db-cluster, il s’agit du répertoire parent et un sous-répertoire est créé pour chaque langage analysé.
--languageSpécifiez l’identificateur de la langue pour laquelle vous souhaitez créer une base de données, l’une des suivantes : c-cpp, csharp, go, java-kotlin, javascript-typescript, python, ruby, and swift. Utilisée avec --db-cluster, l’option accepte une liste séparée par des virgules ou peut être spécifiée plusieurs fois.
--commandRecommandé. Utilisez cette option pour spécifier la commande de génération ou le script qui appelle le processus de génération pour le codebase. Les commandes sont exécutées à partir du dossier actuel ou de --source-root si ce dernier est défini. Non nécessaire pour une analyse Python et JavaScript/TypeScript.
--build-modeRecommandé. Utilisez pour C# et Java quand vous ne fournissez pas de --command pour spécifier s’il faut créer une base de données CodeQL sans génération (none) ou en tentant de détecter automatiquement une commande de génération (autobuild). Par défaut, la détection de génération automatique est utilisée. Pour obtenir une comparaison des modes de génération, consultez « Modes de génération CodeQL ».
--db-clusterUtilisez cette option dans les codebases en plusieurs langages pour générer une seule base de données pour chaque langage spécifié par --language.
--no-run-unnecessary-buildsRecommandé. Utilisez cette option pour supprimer la commande de génération pour les langages où l’CodeQL CLI n’a pas besoin de superviser la génération (par exemple, Python et JavaScript/TypeScript).
--source-rootUtilisez cette option si vous exécutez l’interface CLI en dehors de la racine d’extraction du dépôt. Par défaut, la commande database create suppose que le répertoire actuel est le répertoire racine des fichiers sources. Utilisez cette option pour spécifier un autre emplacement.
--codescanning-configAvancé. À utiliser si vous avez un fichier de configuration qui spécifie comment créer les bases de données CodeQL et quelles requêtes exécuter dans des étapes ultérieures. Pour plus d’informations, consultez « Personnalisation de votre configuration avancée pour l’analyse de code » et « database create ».

Vous pouvez spécifier des options d’extracteur pour personnaliser le comportement des extracteurs qui créent les bases de données CodeQL. Pour plus d’informations, consultez « Options d’extracteur ».

Pour des détails complets sur toutes les options que vous pouvez utiliser lors de la création de bases de données, consultez « database create ».

Exemple avec un langage unique

Cet exemple crée une base de données CodeQL unique pour le référentiel extrait à l'emplacement /checkouts/example-repo. Il utilise l’extracteur JavaScript pour créer une représentation hiérarchique du code JavaScript et TypeScript dans le dépôt. La base de données obtenue est stockée dans /codeql-dbs/example-repo.

$ codeql database create /codeql-dbs/example-repo --language=javascript-typescript \
    --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.

Exemple avec plusieurs langages

Cet exemple crée deux bases de données CodeQL pour le dépôt extrait à l’emplacement /checkouts/example-repo-multi. Il utilise :

  • --db-cluster pour demander l’analyse de plusieurs langages.
  • --language pour spécifier les langages pour lesquels créer des bases de données.
  • --command pour indiquer à l’outil la commande de génération pour le codebase, ici make.
  • --no-run-unnecessary-builds pour indiquer à l’outil d’ignorer la commande de génération pour les langages où elle n’est pas nécessaire (comme Python).

Les bases de données obtenues sont stockées dans les sous-répertoires python et cpp de /codeql-dbs/example-repo-multi.

$ codeql database create /codeql-dbs/example-repo-multi \
    --db-cluster --language python,c-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.
$

Progression et résultats

Des erreurs sont signalées en cas de problèmes avec les options que vous avez spécifiées. Pour les langages interprétés et lorsque vous spécifiez --build-mode none pour C# et Java, la progression de l’extraction s’affiche dans la console. Pour chaque fichier source, la console indique si l’extraction a réussi ou si elle a échoué. Lors de la génération d’un langage compilé, la console affiche le produit du système de génération.

Une fois la base de données créée, vous trouverez un nouveau répertoire dans le chemin spécifié dans la commande. Si vous avez utilisé l’option --db-cluster pour créer plusieurs bases de données, un sous-répertoire est créé pour chaque langage. Chaque répertoire de base de données CodeQL contient un certain nombre de sous-répertoires, notamment les données relationnelles (requises pour l’analyse) et une archive source (une copie des fichiers sources créée au moment de la création de la base de données) qui est utilisée pour afficher les résultats de l’analyse.

Création de bases de données pour les langages non compilés

CodeQL CLI comprend des extracteurs pour créer des bases de données pour les langages non compilés, en particulier JavaScript (et TypeScript), Python et Ruby. Ces extracteurs sont appelés automatiquement lorsque vous spécifiez JavaScript, Python ou Ruby comme option --language lors de l’exécution de database create. Lorsque vous créez des bases de données pour ces langages, vous devez vous assurer que toutes les dépendances supplémentaires sont disponibles.

Note

Lorsque vous exécutez database create pour JavaScript, TypeScript, Python et Ruby, vous ne devez pas spécifier d’option--command. Sinon, cela remplace l’appel de l’extracteur normal, ce qui crée une base de données vide. Si vous créez des bases de données pour plusieurs langages et que l’un d’eux est un langage compilé, utilisez l’option --no-run-unnecessary-builds pour ignorer la commande pour les langages qui n’ont pas besoin d’être compilés.

JavaScript et TypeScript

La création de bases de données pour JavaScript ne nécessite aucune dépendance supplémentaire. Toutefois, si le projet inclut des fichiers TypeScript, Node.js 14 ou une version plus récente doit être installé et disponible sur le serveur PATH comme node. Dans la ligne de commande, vous pouvez spécifier --language=javascript-typescript pour extraire les fichiers JavaScript et TypeScript :

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

Ici, nous avons spécifié un chemin --source-root, qui est l’emplacement où la création de la base de données est exécutée, mais qui n’est pas nécessairement la racine d’extraction du codebase.

Par défaut, les fichiers dans les répertoires node_modules et bower_components ne sont pas extraits.

Python

Lorsque vous créez des bases de données pour Python, vous devez vous assurer que :

  • Python 3 est installé et disponible pour l’extracteur CodeQL.
  • La version de Python utilisée par votre code est installée.

Dans la ligne de commande, vous devez spécifier --language=python. Par exemple :

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

Cette opération exécute la sous-commande database create à partir de la racine d’extraction du code, générant une nouvelle base de données Python dans <output-folder>/python-database.

Ruby

La création de bases de données pour Ruby ne demande aucune dépendance supplémentaire. Dans la ligne de commande, vous devez spécifier --language=ruby. Par exemple :

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

Ici, nous avons spécifié un chemin --source-root, qui est l’emplacement où la création de la base de données est exécutée, mais qui n’est pas nécessairement la racine d’extraction du codebase.

Création de bases de données pour les langages compilés

Pour la majorité des langages compilés, CodeQL doit invoquer le système de génération requis pour générer une base de données. Par conséquent, la méthode de génération doit être disponible pour l’interface CLI. Cette approche crée des bases de données qui incluent du code généré. CodeQL dispose de deux méthodes pour générer des codebases :

En outre, pour C# et Java, il existe une option permettant de générer une base de données sans générer le code. Cela est particulièrement utile lorsque vous souhaitez activer code scanning pour de nombreux référentiels. Pour plus d’informations, consultez « Modes de génération CodeQL ».

Détection automatique du système de génération

L’CodeQL CLI comprend des générateurs automatiques pour le code C/C++, C#, Go, Java, Kotlin et Swift. Les générateurs automatiques CodeQL vous permettent de générer des projets pour les langages compilés sans spécifier de commandes de build. Quand un générateur automatique est appelé, CodeQL examine la source pour confirmer la présence d’un système de build et tente d’exécuter le jeu optimal de commandes requises pour extraire une base de données. Pour plus d’informations, consultez « Analyse du code CodeQL pour les langages compilés ».

Un générateur automatique est invoqué automatiquement lorsque vous exécutez codeql database create pour un langage compilé si vous n’incluez pas d’option --command ou ne définissez pas --build-mode none. Par exemple, pour une codebase C/C++, vous pouvez simplement exécuter :

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

Si un codebase utilise un système de build standard, s’appuyer sur un générateur automatique est souvent le moyen le plus simple de créer une base de données. Pour les sources qui demandent des étapes de génération non standard, vous devrez peut-être définir explicitement chaque étape dans la ligne de commande.

Note

  • Si vous créez une base de données Go, installez la chaîne d’outils Go (version 1.11 ou ultérieure) et, s’il existe des dépendances, le gestionnaire de dépendances approprié (par exemple dep).
  • Le générateur automatique Go tente de détecter automatiquement le code écrit en Go dans un dépôt et exécute uniquement les scripts de build dans une tentative de récupération des dépendances. Pour forcer CodeQL à limiter l’extraction aux fichiers compilés par votre script de build, définissez la variable d’environnement CODEQL_EXTRACTOR_GO_BUILD_TRACING=on ou utilisez l’option --command pour spécifier une commande de build.

Spécification des commandes de build

Les exemples suivants sont conçus pour vous donner une idée de quelques commandes de build que vous pouvez spécifier pour les langages compilés.

Note

L’option --command accepte un seul argument. Si vous devez utiliser plusieurs commandes, spécifiez --command plusieurs fois. Si vous devez passer des sous-commandes et des options, l’argument entier doit être entre guillemets pour être interprété correctement.

  • Projet C/C++ généré avec make :

    codeql database create cpp-database --language=c-cpp --command=make
    
  • Projet C# généré avec dotnet build :

    Il est judicieux d’ajouter /t:rebuild pour vous assurer que tout le code sera généré ou d’effectuer un dotnet clean avant (le code qui n’est pas généré ne sera pas inclus dans la base de données CodeQL) :

    codeql database create csharp-database --language=csharp --command='dotnet build /t:rebuild'
    
  • Projet Go généré avec la variable d’environnement CODEQL_EXTRACTOR_GO_BUILD_TRACING=on :

    CODEQL_EXTRACTOR_GO_BUILD_TRACING=on codeql database create go-database --language=go
    
  • Projet Go généré avec un script de build personnalisé :

    codeql database create go-database --language=go --command='./scripts/build.sh'
    
  • Projet Java généré avec Gradle :

    # 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-kotlin --command='gradle --no-daemon clean test'
    
  • Projet Java généré avec Maven :

    codeql database create java-database --language=java-kotlin --command='mvn clean install'
    
  • Projet Java généré avec Ant :

    codeql database create java-database --language=java-kotlin --command='ant -f build.xml'
    
  • Projet Swift créé à partir d’un projet ou d’un espace de travail Xcode. Par défaut, la plus grande cible Swift est générée :

    Il est conseillé de s'assurer que le projet est dans un état propre et qu'il n'y a pas d'artefacts de construction disponibles.

    xcodebuild clean -all
    codeql database create -l swift swift-database
    
  • Projet Swift généré avec swift build :

    codeql database create -l swift -c "swift build" swift-database
    
  • Projet Swift généré avec xcodebuild :

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

    Vous pouvez passer les options archive et test à xcodebuild. Toutefois, la commande standard xcodebuild est recommandée, car elle doit être la plus rapide et doit être tout ce que CodeQL nécessite pour une analyse réussie.

  • Projet Swift généré avec un script de build personnalisé :

    codeql database create -l swift -c "./scripts/build.sh" swift-database
    
  • Projet généré avec 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
    
  • Projet généré avec un script de build personnalisé :

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

Cette commande exécute un script personnalisé qui contient toutes les commandes requises pour générer le projet.

Utilisation du traçage de build indirect

Si les générateurs automatiques CodeQL CLI pour les langages compilés ne fonctionnent pas avec votre workflow CI et que vous ne pouvez pas wrapper les appels de commandes de build avec codeql database trace-command, vous pouvez utiliser le traçage de build indirect pour créer une base de données CodeQL. Pour utiliser le traçage de build indirect, votre système CI doit être en mesure de définir des variables d’environnement personnalisées pour chaque action de génération.

Pour créer une base de données CodeQL avec le traçage de build indirect, exécutez la commande suivante à partir de la racine d’extraction de votre projet :

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

Vous devez spécifier :

  • <database> : chemin de la nouvelle base de données à créer. Ce répertoire est créé lorsque vous exécutez la commande. Vous ne pouvez pas spécifier de répertoire existant.
  • --begin-tracing : crée des scripts qui peuvent être utilisés pour configurer un environnement dans lequel les commandes de build seront tracées.

Vous pouvez spécifier d’autres options pour la commande codeql database init comme d’habitude.

Note

Si la compilation s'effectue sous Windows, vous devez définir l'option --trace-process-level <number> ou --trace-process-name <parent process name> de manière à ce qu'elle pointe vers un processus CI parent qui observera toutes les étapes de la compilation pour le code analysé.

La commande codeql database init génère un message :

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: ...

La commande codeql database init crée <database>/temp/tracingEnvironment avec des fichiers qui contiennent des variables d’environnement et des valeurs qui permettent à CodeQL de tracer une séquence d’étapes de génération. Ces fichiers sont appelés start-tracing.{json,sh,bat,ps1}. Utilisez l’un de ces fichiers avec le mécanisme de votre système CI afin de définir les variables d’environnement pour les étapes futures. Vous pouvez :

  • Lisez le fichier JSON, traitez-le et affichez les variables d’environnement au format attendu par votre système CI. Par exemple, Azure DevOps attend echo "##vso[task.setvariable variable=NAME]VALUE".
  • Ou, si votre système CI conserve l’environnement, sourcez le script start-tracing approprié pour définir les variables CodeQL dans l’environnement shell du système CI.

Générez votre code, et annulez si vous voulez les variables d’environnement à l’aide d’un script end-tracing.{json,sh,bat,ps1} du répertoire où les scripts start-tracing sont stockés, puis exécutez la commande codeql database finalize <database>.

Une fois que vous avez créé une base de données CodeQL à l’aide du traçage de build indirect, vous pouvez l’utiliser comme n’importe quelle autre base de données CodeQL. Par exemple, analysez la base de données et chargez les résultats dans GitHub si vous utilisez l’analyse du code.

Exemple de création d’une base de données CodeQL à l’aide du traçage de build indirect

Note

Si vous utilisez des pipelines Azure DevOps, le moyen le plus simple de créer une base de données CodeQL consiste à utiliser GitHub Advanced Security for Azure DevOps. Pour obtenir de la documentation, consultez Configurer GitHub Advanced Security for Azure DevOps dans Microsoft Learn.

L’exemple suivant montre comment vous pourriez utiliser le traçage de build indirect dans un pipeline Azure DevOps pour créer une base de données 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` ...

Étapes suivantes