Skip to main content

Como preparar seu código para a análise do CodeQL

Você pode criar um CodeQL banco de dados contendo os dados necessários para analisar seu código.

Quem pode usar esse recurso?

Usuários com acesso de leitura a um repositório

O CodeQL está disponível para os seguintes tipos de repositórios:

Sobre como preparar seu código para análise

Observação

Este artigo descreve os recursos disponíveis com o pacote CodeQL CLI 2.20.7 incluído na versão inicial do GitHub Enterprise Server 3.17.

Se o administrador do site atualizou a versão do CodeQL CLI para uma mais recente, confira a versão GitHub Enterprise Cloud deste artigo para obter informações sobre os recursos mais recentes.

Antes de analisar seu código usando CodeQL, você precisa criar um banco de dados CodeQL contendo todos os dados necessários para executar consultas no seu código. Você pode criar CodeQL bancos de dados por conta própria usando o CodeQL CLI.

CodeQL A análise depende da extração de dados relacionais do código e do uso dele para criar um CodeQL banco de dados. CodeQL os bancos de dados contêm todas as informações importantes sobre uma base de código, que podem ser analisadas executando CodeQL consultas nele.

Antes de gerar um CodeQL banco de dados, você precisa:

  1. Instale e configure o CodeQL CLI. Para obter mais informações, consulte Como configurar a CLI do CodeQL.
  2. Confira o código que você deseja analisar:
    • Para uma ramificação, confira o cabeçalho da ramificação que você deseja analisar.
    • Para obter uma solicitação de pull, confira a confirmação principal da solicitação de pull ou confira uma GitHubconfirmação de mesclagem gerada da solicitação de pull.
  3. Configure o ambiente para a base de código, verificando se todas as dependências estão disponíveis.
  4. Para melhores resultados com linguagens compiladas, encontre o comando de compilação (se houver) para a sua base de código. Normalmente, isso está disponível em um arquivo de configuração no sistema de CI.

Quando a base de código estiver pronta, execute codeql database create para criar o banco de dados. Para obter mais informações, consulte Criando bancos de dados para linguagens não compiladas e Criando bancos de dados para linguagens compiladas.

Em execução codeql database create

CodeQL os bancos de dados são criados ao executar o seguinte comando a partir da raiz do checkout do seu projeto:

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

É preciso especificar:

  • <database>: um caminho para o novo banco de dados a ser criado. Esse diretório será criado quando você executar o comando. Não é possível especificar um diretório existente.

  • --language: o identificador do idioma para o qual será criado um banco de dados. Quando usado com --db-cluster, a opção aceita uma lista separada por vírgulas ou pode ser especificada mais de uma vez. CodeQL dá suporte à criação de bancos de dados para os seguintes idiomas:

    LinguagemIdentificadorIdentificadores alternativos opcionais (se houver)
    C/C++c-cpp
    c ou cpp
    C#csharp
    Gogo
    Java/Kotlinjava-kotlin
    java ou kotlin
    JavaScript/TypeScriptjavascript-typescript
    javascript ou typescript
    Pythonpython
    Rubyruby
    Rust (versão prévia pública)rust
    Swiftswift

    Observação

    Especificar um dos identificadores alternativos equivale a usar o identificador de linguagem padrão. Por exemplo, especificar javascript em vez de javascript-typescript não excluirá a análise do código TypeScript. Em vez disso, você pode usar a opção da CLI --codescanning-config para carregar um arquivo de configuração que especifica os arquivos a serem excluídos com a chave de configuração paths-ignore. Consulte Opções de configuração de fluxo de trabalho para verificação de código.

    Como alternativa, para linguagens que dão suporte, use um comando de build personalizado que compila apenas os arquivos que você deseja verificar. Confira Como criar bancos de dados para linguagens compiladas.

Se a sua base de código tiver um comando ou script de compilação que invoque o processo de compilação, recomendamos que você o especifique também:

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

Opções para criar bancos de dados

Você pode especificar opções adicionais dependendo do local do arquivo de origem, se o código precisar ser compilado e se quiser criar CodeQL bancos de dados para mais de um idioma.

OpçãoObrigatórioUso
<database>Especifique o nome e o local de um diretório a ser criado para o CodeQL banco de dados. O comando falhará se você tentar substituir um diretório. Se você também especificar --db-cluster, esse será o diretório pai e um subdiretório será criado para cada linguagem analisada.
--languageEspecifique o identificador para o idioma para o qual criar um banco de dados, um de: c-cpp, csharp, go, java-kotlin, javascript-typescript, python, ruby e swift. Quando usado com --db-cluster, a opção aceita uma lista separada por vírgulas ou pode ser especificada mais de uma vez.
--command
Recomendado. Use para especificar o comando ou o script de build que invoca o processo de build para a base de código. Os comandos são executados a partir da pasta atual ou, quando definido, a partir de --source-root. Não é necessário para análise de Python e JavaScript/TypeScript.
--build-mode
Recomendado. Use para C# e Java quando não fornecer um --command para especificar se um banco de dados CodeQL deve ser criado sem um build (none) ou tentando detectar automaticamente um comando de build (autobuild). Por padrão, a detecção de compilação automática é usada. Para uma comparação dos modos de compilação, consulte Modos de compilação do CodeQL.
--db-clusterUtilize em bases de código multilíngues para gerar um banco de dados para cada idioma especificado por --language.
--no-run-unnecessary-builds
Recomendado. Use para suprimir o comando de build para idiomas em que o CodeQL CLI não precisa monitorar o build (por exemplo, Python e JavaScript/TypeScript).
--source-rootUse se você executa a CLI fora da raiz de check-out do repositório. Por padrão, o comando database create pressupõe que o diretório atual seja o diretório raiz dos arquivos de origem. Use essa opção para especificar outro local.
--codescanning-configAdvanced. Use se você tiver um arquivo de configuração que especifique como criar os CodeQL bancos de dados e quais consultas serão executadas em etapas posteriores. Para obter mais informações, consulte Opções de configuração de fluxo de trabalho para verificação de código e criação de banco de dados.

Você pode especificar opções de extrator para personalizar o comportamento dos extratores que criam CodeQL bancos de dados. Para obter mais informações, consulte Opções do extrator.

Para obter detalhes completos sobre todas as opções que você pode usar ao criar bancos de dados, consulte criação de banco de dados.

Exemplo de linguagem única

Este exemplo cria um único banco de dados CodeQL para o repositório obtido em /checkouts/example-repo. Ele usa o extrator de JavaScript para criar uma representação hierárquica do código JavaScript e TypeScript no repositório. O banco de dados resultante é armazenado no /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.

Exemplo de linguagem múltipla

Este exemplo cria dois CodeQL bancos de dados para o repositório obtido em /checkouts/example-repo-multi. Utiliza:

  • --db-cluster solicitar a análise de mais de um idioma.
  • --language para especificar em quais idiomas criar bancos de dados.
  • --command para informar à ferramenta o comando de compilação para a base de código, aqui. make.
  • --no-run-unnecessary-builds para informar à ferramenta para ignorar o comando de build para idiomas em que ele não é necessário (como Python).

Os bancos de dados resultantes são armazenados em subdiretórios python e cpp do /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.
$

Progresso e resultados

Erros serão relatados se houver problemas com as opções especificadas. Em linguagens interpretadas e, ao especificar --build-mode none para C# e Java, o progresso da extração é exibido no console. Para cada arquivo de origem, o console mostra se a extração foi bem-sucedida ou se falhou. Quando uma linguagem é compilada, o console exibirá a saída do sistema de build.

Quando o banco de dados for criado com êxito, haverá um novo diretório no caminho especificado no comando. Se você usou a opção --db-cluster para criar mais de um banco de dados, um subdiretório será criado para cada linguagem. Cada CodeQL diretório de banco de dados contém uma série de subdiretórios, incluindo os dados relacionais (necessários para análise) e um arquivo de origem , uma cópia dos arquivos de origem feitas no momento em que o banco de dados foi criado, que é usado para exibir os resultados da análise.

Como criar bancos de dados para linguagens não compiladas

O CodeQL CLI inclui extratores para criar bancos de dados para idiomas não compilados , especificamente, JavaScript (e TypeScript), Python e Ruby. Esses extratores são invocados automaticamente quando você especifica JavaScript, Python ou Ruby como a opção --language ao executar database create. Ao criar bancos de dados para essas linguagens, você precisa garantir que todas as dependências adicionais estejam disponíveis.

Observação

Ao executar database create para JavaScript, TypeScript, Python e Ruby, você não deve especificar uma opção --command. Caso contrário, isso substituirá a invocação normal do extrator, que criará um banco de dados vazio. Se você criar bancos de dados para várias linguagens e uma delas for uma linguagem compilada, use a opção --no-run-unnecessary-builds para ignorar o comando em linguagens que não precisam ser compiladas.

JavaScript e TypeScript

A criação de bancos de dados para JavaScript não requer dependências adicionais, mas se o projeto incluir arquivos TypeScript, o Node.js 14 ou superior precisará ser instalado e estar disponível no PATH como node. Na linha de comando, você pode especificar --language=javascript-typescript para extrair arquivos JavaScript e TypeScript:

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

Aqui, especificamos um caminho --source-root, que é o local em que a criação do banco de dados é executada, mas não é necessariamente a raiz de check-out da base de código.

Por padrão, os arquivos nos diretórios node_modules e bower_components não são extraídos.

Python

Ao criar bancos de dados para Python você deve garantir:

  • Você tem o Python 3 instalado e disponível para o extrator CodeQL.
  • Você tem instalada a versão do Python usada pelo seu código.

Na linha de comando, você precisa especificar --language=python. Por exemplo:

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

Isso executa o subcomando database create a partir da raiz de checkout do código, criando um novo banco de dados Python em <output-folder>/python-database.

Ruby

A criação de bancos de dados para Ruby não requer dependências adicionais. Na linha de comando, você precisa especificar --language=ruby. Por exemplo:

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

Aqui, especificamos um caminho --source-root, que é o local em que a criação do banco de dados é executada, mas não é necessariamente a raiz de check-out da base de código.

Como criar bancos de dados para linguagens compiladas

Para a maioria dos idiomas compilados, CodeQL é necessário invocar o sistema de build necessário para gerar um banco de dados, portanto, o método de build deve estar disponível para a CLI. Essa abordagem cria bancos de dados que incluem código gerado. CodeQL tem dois métodos para a criação de bases de código:

Além disso, para C# e Java, há uma opção para gerar um banco de dados sem compilar o código. Isso é particularmente útil quando você deseja habilitar code scanning para muitos repositórios. Para mais informações, consulte Modos de compilação do CodeQL.

Detectando o sistema de compilação automaticamente

O CodeQL CLI inclui autobuilders para código C/C++, C#, Go, Java, Kotlin e Swift. CodeQL Os autobuilders permitem que você crie projetos para idiomas compilados sem especificar comandos de build. Quando um autobuilder é invocado, CodeQL examina a origem para obter evidências de um sistema de build e tenta executar o conjunto ideal de comandos necessários para extrair um banco de dados. Para obter mais informações, consulte CodeQL code scanning for compiled languages.

Um compilador automático será chamado automaticamente quando você executar codeql database create para uma linguagem compilada se você não incluir uma opção --command ou definir --build-mode none. Por exemplo, para uma base de código Swift, você poderia simplesmente executar:

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

Se uma base de código usa um sistema de build padrão, a dependência de um construtor automático geralmente é a maneira mais simples de criar um banco de dados. Para fontes que exigem etapas de build não padrão, talvez seja necessário definir explicitamente cada etapa na linha de comando.

Observação

  • Se você estiver criando um banco de dados Go, instale a cadeia de ferramentas Go (versão 1.11 ou posterior) e, se houver dependências, o gerenciador de dependências apropriado (como o dep).
  • O construtor automático Go tenta detectar automaticamente o código escrito em Go em um repositório e executa apenas scripts de build na tentativa de buscar dependências. Para forçar CodeQL a limitação da extração aos arquivos compilados pelo script de build, defina a variável CODEQL_EXTRACTOR_GO_BUILD_TRACING=on de ambiente ou use a opção --command para especificar um comando de build.

Como especificar comandos de build

Os exemplos a seguir foram projetados para dar uma ideia de alguns dos comandos de build que você pode especificar para linguagens compiladas.

Observação

A opção --command aceita um único argumento—se precisar usar mais de um comando, especifique --command várias vezes. Se você precisar passar subcomandos e opções, todo o argumento precisará ser colocado entre aspas para ser interpretado corretamente.

  • Projeto C/C++ criado usando make:

    # Disable parallel execution via `-j1` or other techniques: https://www.gnu.org/software/make/manual/make.html#Parallel-Execution
    codeql database create cpp-database --language=c-cpp --command=make
    
  • Projeto C# criado usando dotnet build:

    É uma boa ideia adicionar /t:rebuild para garantir que todo o código seja compilado, ou fazer previamente um dotnet clean (o código que não for compilado não será incluído no banco de dados CodeQL):

    codeql database create csharp-database --language=csharp --command='dotnet build /t:rebuild'
    
  • Projeto Go criado usando a variável de ambiente CODEQL_EXTRACTOR_GO_BUILD_TRACING=on:

    CODEQL_EXTRACTOR_GO_BUILD_TRACING=on codeql database create go-database --language=go
    
  • Projeto Go criado usando um script de build personalizado:

    codeql database create go-database --language=go --command='./scripts/build.sh'
    
  • Java projeto criado usando o 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'
    
  • Java projeto criado usando o Maven:

    codeql database create java-database --language=java-kotlin --command='mvn clean install'
    
  • Java projeto criado usando Ant:

    codeql database create java-database --language=java-kotlin --command='ant -f build.xml'
    
  • Projeto Swift criado a partir de um projeto ou workspace do Xcode. Por padrão, o maior destino Swift é criado:

    É uma boa ideia garantir que o projeto esteja limpo e que não haja artefatos de compilação disponíveis.

    xcodebuild clean -all
    codeql database create -l swift swift-database
    
  • Projeto Swift criado com swift build:

    codeql database create -l swift -c "swift build" swift-database
    
  • Projeto Swift criado com xcodebuild:

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

    Você pode passar as opções archive e test para xcodebuild. No entanto, o comando padrão xcodebuild é recomendado, pois deve ser o mais rápido e deve ser tudo o que CodeQL requer para uma verificação bem-sucedida.

  • Projeto Swift criado usando um script de build personalizado:

    codeql database create -l swift -c "./scripts/build.sh" swift-database
    
  • Projeto criado usando o 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
    

Observação

Atualmente, não há suporte para o build do Bazel para Go.

  • Projeto criado usando um script de build personalizado:

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

Esse comando executa um script personalizado que contém todos os comandos necessários para compilar o projeto.

Como usar o rastreamento de build indireto

Se os CodeQL CLI autobuilders para linguagens compiladas não funcionarem com seu fluxo de trabalho de CI e você não puder envolver as invocações de comandos de compilação com codeql database trace-command, poderá usar o rastreamento indireto da compilação para criar um banco de dados CodeQL. Para usar o rastreamento de build indireto, o sistema de CI precisa ser capaz de definir variáveis de ambiente personalizadas para cada ação de build.

Para criar um banco de dados CodeQL com rastreamento indireto da compilação, execute o comando a seguir no diretório raiz do checkout do seu projeto:

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

É preciso especificar:

  • <database>: um caminho para o novo banco de dados a ser criado. Esse diretório será criado quando você executar o comando. Não é possível especificar um diretório existente.
  • --begin-tracing: cria scripts que podem ser usados​para configurar um ambiente no qual os comandos de compilação serão rastreados.

Você pode especificar outras opções para o comando codeql database init como de costume.

Observação

Se a compilação for executada no Windows, é necessário definir --trace-process-level <number> ou --trace-process-name <parent process name> para que a opção direcione para um processo pai de CI que observará todas as etapas da compilação para o código que está sendo analisado.

O comando codeql database init vai gerar uma mensagem:

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

O codeql database init comando cria <database>/temp/tracingEnvironment com arquivos que contêm variáveis de ambiente e valores que permitirão CodeQL rastrear uma sequência de etapas de build. Esses arquivos são chamados de start-tracing.{json,sh,bat,ps1}. Use um desses arquivos com o mecanismo do sistema de CI para definir variáveis de ambiente de etapas futuras. É possível:

  • Ler o arquivo JSON, processá-lo e imprimir variáveis de ambiente no formato esperado pelo sistema de CI. Por exemplo, Azure DevOps espera echo "##vso[task.setvariable variable=NAME]VALUE".
  • Ou, se o sistema de CI persistir o ambiente, crie o script apropriado start-tracing para definir as CodeQL variáveis no ambiente de shell do sistema de CI.

Crie o código. Opcionalmente, remova a definição das variáveis de ambiente usando um script end-tracing.{json,sh,bat,ps1} do diretório em que os scripts start-tracing são armazenados e depois execute o comando codeql database finalize <database>.

Depois de criar um banco de dados CodeQL usando o rastreamento indireto de build, você pode trabalhar com ele como com qualquer outro banco de dados CodeQL. Por exemplo, analise o banco de dados e envie os resultados para GitHub, se você usa a verificação de código.

Exemplo de criação de um banco de dados CodeQL com rastreamento indireto de compilação

Observação

Se você usar Azure DevOps pipelines, a maneira mais simples de criar um banco de dados CodeQL será usar GitHub Advanced Security for Azure DevOps. Para obter documentação, consulte Configure GitHub Advanced Security for Azure DevOps no Microsoft Learn.

O exemplo a seguir mostra como você pode usar o rastreamento de build indireto em um pipeline de Azure DevOps para criar um banco de dados 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` ...

Próximas Etapas