Skip to main content

Preparación del código para el análisis de CodeQL

Puede crear una CodeQL base de datos que contenga los datos necesarios para analizar el código.

¿Quién puede utilizar esta característica?

Usuarios con acceso de lectura a un repositorio

CodeQL está disponible para los siguientes tipos de repositorios:

Acerca de la preparación del código para el análisis

Nota:

En este artículo, se describen las características disponibles con el paquete CodeQL CLI 2.20.7 que se incluye en la versión inicial de GitHub Enterprise Server 3.17.

Si el administrador del sitio ha actualizado tu versión de la CodeQL CLI a una versión más reciente, consulta la versión de GitHub Enterprise Cloud de este artículo para obtener información sobre las características más recientes.

Antes de analizar el código mediante CodeQL, debe crear una CodeQL base de datos que contenga todos los datos necesarios para ejecutar consultas en el código. Puede crear usted mismo bases de datos CodeQL usando CodeQL CLI.

CodeQL el análisis se basa en la extracción de datos relacionales del código y su uso para compilar una CodeQL base de datos. CodeQL Las bases de datos contienen toda la información importante sobre un código base, que se puede analizar mediante la ejecución de CodeQL consultas en él.

Antes de generar una CodeQL base de datos, debe:

  1. Instale y configure el CodeQL CLI. Para obtener más información, vea Configuración de la CLI de CodeQL.
  2. Extraiga del repositorio el código que quiera analizar:
    • En el caso de una rama, extraiga del repositorio el inicio de la rama que quiera analizar.
    • Para una solicitud de incorporación de cambios, consulte la confirmación principal de la solicitud de incorporación de cambios o consulte una GitHubconfirmación de combinación generada por la solicitud de incorporación de cambios.
  3. Configure el entorno para el código base y asegúrese de que las dependencias estén disponibles.
  4. Para obtener los mejores resultados con lenguajes compilados, busque el comando build, si existe, para el código base. Normalmente está disponible en un archivo de configuración en el sistema de CI.

Una vez que el código base esté listo, puedes ejecutar codeql database create para crear la base de datos. Para obtener más información, consulte Creación de bases de datos para lenguajes no compilados y Creación de bases de datos para lenguajes compilados.

En ejecución codeql database create

CodeQL Las bases de datos se crean mediante la ejecución del siguiente comando desde la raíz de desprotección del proyecto:

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

Debe especificar:

  • <database>: una ruta de acceso a la base de datos nueva que se va a crear. Este directorio se creará al ejecutar el comando; no se puede especificar un directorio existente.

  • --language: el identificador del lenguaje para el que se va a crear una base de datos. Cuando se usa con --db-cluster, la opción acepta una lista separada por comas o se puede especificar más de una vez. CodeQL admite la creación de bases de datos para los siguientes idiomas:

    LenguajeIdentificadorIdentificadores alternativos opcionales (si los hay)
    C/C++c-cpp
    c o cpp
    C#csharp
    Gogo
    Java/Kotlinjava-kotlin
    java o kotlin
    JavaScript/TypeScriptjavascript-typescript
    javascript o typescript
    Pythonpython
    Rubyruby
    Rust (versión preliminar pública)rust
    Swiftswift

    Nota:

    Si especificas uno de los identificadores alternativos, esto equivale a usar el identificador de idioma estándar. Por ejemplo, especificar javascript en lugar de javascript-typescript no excluirá el análisis del código TypeScript. En su lugar, puedes usar la opción --codescanning-config CLI para cargar un archivo de configuración que especifique los archivos que se excluirán con la clave de configuración paths-ignore. Consulte Opciones de configuración de flujo de trabajo para el examen de código.

    Como alternativa, para los lenguajes que lo admiten, usa un comando de compilación personalizado que solo compile los archivos que deseas examinar. Consulta Creación de bases de datos para lenguajes compilados.

Si el código base tiene un comando de compilación o un script que invoca el proceso de compilación, se recomienda especificarlo también:

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

Opciones para crear bases de datos

Puede especificar opciones adicionales en función de la ubicación del archivo de origen, si es necesario compilar el código y si desea crear CodeQL bases de datos para más de un idioma.

OpciónObligatorioUso
<database>Especifique el nombre y la ubicación de un directorio que se va a crear para la CodeQL base de datos. Se producirá un error en el comando si intenta sobrescribir un directorio existente. Si también especifica --db-cluster, este es el directorio primario y se crea un subdirectorio para cada lenguaje analizado.
--languageEspecifique el identificador del idioma para el que se va a crear una base de datos, una de las siguientes: c-cpp, csharp, go, java-kotlin, javascript-typescript, python``ruby y swift. Cuando se usa con --db-cluster, la opción acepta una lista separada por comas o se puede especificar más de una vez.
--command
Opción recomendada. Se usa para especificar el comando de compilación o el script que invoca el proceso de compilación para el código base. Los comandos se ejecutan desde la carpeta actual o, donde se define, desde --source-root. No es necesario para el análisis de Python y JavaScript o TypeScript.
--build-mode
Opción recomendada. Se utiliza con C# y Java cuando no se proporciona un --command para especificar si se debe crear una base de datos de CodeQL sin una compilación (none) o intentando detectar automáticamente un comando de compilación (autobuild). De forma predeterminada, se usa la detección de Autobuild. Para obtener una comparación de los modos de compilación, consulta Modos de compilación de CodeQL.
--db-clusterSe usa en códigos base de varios lenguajes para generar una base de datos para cada lenguaje especificado por --language.
--no-run-unnecessary-builds
Opción recomendada. Use para suprimir el comando de compilación para los lenguajes en los que el CodeQL CLI no necesita supervisar la compilación (por ejemplo, Python y JavaScript/TypeScript).
--source-rootSe usa si ejecuta la CLI fuera de la raíz de extracción del repositorio. De manera predeterminada, el comando database create supone que el directorio actual es el directorio raíz de los archivos de origen. Use esta opción para especificar otra ubicación.
--codescanning-configAvanzado. Úselo si tiene un archivo de configuración que especifica cómo crear las bases de datos CodeQL y qué consultas ejecutar en los pasos posteriores. Para obtener más información, vea Opciones de configuración de flujo de trabajo para el examen de código y creación de base de datos.

Puede especificar opciones de extractor para personalizar el comportamiento de los extractores que crean CodeQL bases de datos. Para obtener más información, vea Opciones de extractor.

Para obtener información detallada sobre todas las opciones que se pueden usar al crear bases de datos, consulte creación de base de datos.

Ejemplo de un solo lenguaje

En este ejemplo se crea una única base de datos CodeQL para el repositorio extraído en /checkouts/example-repo. Usa el extractor de JavaScript para crear una representación jerárquica del código JavaScript y TypeScript en el repositorio. La base de datos resultante se almacena en /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.

Ejemplo de lenguaje múltiple

En este ejemplo se crean dos bases de datos CodeQL para el repositorio extraído en /checkouts/example-repo-multi. Utiliza:

  • --db-cluster para solicitar el análisis de más de un lenguaje.
  • --language para especificar los lenguajes para los que se crearán las bases de datos.
  • --command para indicarle a la herramienta el comando de compilación para el código base, en este caso make.
  • --no-run-unnecessary-builds para indicar a la herramienta que omita el comando de compilación de los lenguajes en los que no sea necesario (como Python).

Las bases de datos resultantes se almacenan en los subdirectorios python y 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.
$

Progreso y resultados

Los errores se notifican si hay algún problema con las opciones especificadas. En el caso de los idiomas interpretados y cuando se especifica --build-mode none para C# y Java, el progreso de la extracción se muestra en la consola. Para cada archivo de origen, la consola muestra si la extracción se realizó correctamente o si se produjo un error. En el caso de los lenguajes compilados, la consola mostrará la salida del sistema de compilación.

Cuando la base de datos se crea correctamente, encontrarás un directorio nuevo en la ruta de acceso especificada en el comando. Si usaste la opción --db-cluster para crear más de una base de datos, se crea un subdirectorio para cada lenguaje. Cada CodeQL directorio de base de datos contiene varios subdirectorios, incluidos los datos relacionales (necesarios para el análisis) y un archivo de origen, una copia de los archivos de origen realizados en el momento en que se creó la base de datos, que se usa para mostrar los resultados del análisis.

Creación de bases de datos para lenguajes no compilados

El CodeQL CLI incluye extractores para crear bases de datos para lenguajes no compilados, específicamente JavaScript (y TypeScript), Python y Ruby. Estos extractores se invocan automáticamente al especificar JavaScript, Python o Ruby como la opción --language al ejecutar database create. Al crear bases de datos para estos lenguajes, debes asegurarte de que todas las dependencias adicionales están disponibles.

Nota:

Al ejecutar database create para JavaScript, TypeScript, Python y Ruby, no debe especificar una opción --command. De lo contrario, invalidará la invocación de extractor normal, que creará una base de datos vacía. Si creas bases de datos para varios lenguajes y uno de ellos es un lenguaje compilado, usa la opción --no-run-unnecessary-builds a fin de omitir el comando de los lenguajes que no sea necesario compilar.

JavaScript y TypeScript

La creación de bases de datos para JavaScript no requiere dependencias adicionales, pero si el proyecto incluye archivos TypeScript, debes instalar Node.js 14 o una versión posterior que debe estar disponible en PATH como node. En la línea de comandos, puedes especificar --language=javascript-typescript para extraer archivos JavaScript y TypeScript:

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

Aquí hemos especificado una ruta de acceso --source-root, que es la ubicación donde se ejecuta la creación de la base de datos, pero no es necesariamente la raíz de restauración del código base.

De manera predeterminada, los archivos de los directorios node_modules y bower_components no se extraen.

Python

Al crear bases de datos para Python debe asegurarse de lo siguiente:

  • Tiene Python 3 instalado y accesible para el extractor CodeQL.
  • Tiene instalada la versión de Python usada por su código.

En la línea de comandos, debes especificar --language=python. Por ejemplo:

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

Esto ejecuta el subcomando database create desde la raíz de restauración del código, lo que genera una base de datos de Python nueva en <output-folder>/python-database.

Ruby

La creación de bases de datos para Ruby no requiere dependencias adicionales. En la línea de comandos, debes especificar --language=ruby. Por ejemplo:

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

Aquí hemos especificado una ruta de acceso --source-root, que es la ubicación donde se ejecuta la creación de la base de datos, pero no es necesariamente la raíz de restauración del código base.

Creación de bases de datos para lenguajes compilados

Para la mayoría de los lenguajes compilados, CodeQL debe invocar el sistema de compilación necesario para generar una base de datos, por lo que el método de compilación debe estar disponible para la CLI. Este enfoque crea bases de datos que incluyen código generado. CodeQL tiene dos métodos para compilar código base:

Además, para C# y Java, hay una opción para generar una base de datos sin compilar el código. Esto resulta especialmente útil cuando se desea habilitar code scanning para muchos repositorios. Para más información, consulta Modos de compilación de CodeQL.

Detección automática del sistema de compilación

CodeQL CLI incluye compiladores automáticos para código C/C++, C#, Go, Java, Kotlin y Swift. CodeQL Los autobuilders permiten compilar proyectos para lenguajes compilados sin especificar comandos de compilación. Cuando se invoca un autobuilder, CodeQL examina el origen de la evidencia de un sistema de compilación e intenta ejecutar el conjunto óptimo de comandos necesarios para extraer una base de datos. Para obtener más información, vea CodeQL code scanning for compiled languages.

Un compilador automático se invoca automáticamente cuando se ejecuta codeql database create para un lenguaje compilado si no incluyes una opción --command o estableces --build-mode none. Por ejemplo, para un código base en Swift, puedes ejecutar simplemente:

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

Si un código base usa un sistema de compilación estándar, basarse en un generador automático suele ser la manera más sencilla de crear una base de datos. En el caso de los orígenes que requieren pasos de compilación que no son estándar, es posible que tengas que definir de forma explícita cada paso en la línea de comandos.

Nota:

  • Si vas a compilar una base de datos de Go, instala la cadena de herramientas de Go (versión 1.11 o una posterior) y, si hay dependencias, el administrador de dependencias adecuado (por ejemplo, dep).
  • El generador automático de Go intenta detectar automáticamente el código escrito en Go en un repositorio y solo ejecuta scripts de compilación en un intento de capturar dependencias. Para forzar CodeQL a limitar la extracción a los archivos compilados por el script de compilación, establezca la variable CODEQL_EXTRACTOR_GO_BUILD_TRACING=on de entorno o use la --command opción para especificar un comando de compilación.

Especificación de comandos de compilación

Los ejemplos siguientes están pensados para darte una idea de algunos de los comandos de compilación que puedes especificar para los lenguajes compilados.

Nota:

La opción --command acepta un único argumento; si necesita usar más de un comando, especifique --command varias veces. Si necesitas pasar subcomandos y opciones, el argumento entero debe ir entre comillas para que se interprete correctamente.

  • Proyecto de C/C++ compilado con 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
    
  • Proyecto de C# compilado con dotnet build:

    Es recomendable agregar /t:rebuild para asegurarse de que se compilará todo el código o haga un anterior dotnet clean (el código que no está compilado no se incluirá en la CodeQL base de datos):

    codeql database create csharp-database --language=csharp --command='dotnet build /t:rebuild'
    
  • Ve al proyecto compilado con la variable de entorno CODEQL_EXTRACTOR_GO_BUILD_TRACING=on:

    CODEQL_EXTRACTOR_GO_BUILD_TRACING=on codeql database create go-database --language=go
    
  • Ve al proyecto compilado con un script de compilación personalizado:

    codeql database create go-database --language=go --command='./scripts/build.sh'
    
  • Java proyecto creado con 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 proyecto creado con Maven:

    codeql database create java-database --language=java-kotlin --command='mvn clean install'
    
  • Java proyecto creado con Ant:

    codeql database create java-database --language=java-kotlin --command='ant -f build.xml'
    
  • Proyecto de Swift compilado con un proyecto o área de trabajo de Xcode. De forma predeterminada, se compila el destino de Swift más grande:

    Es una buena idea asegurarse de que el proyecto está en un estado limpio y de que no hay artefactos de compilación disponibles.

    xcodebuild clean -all
    codeql database create -l swift swift-database
    
  • Proyecto de Swift compilado con swift build:

    codeql database create -l swift -c "swift build" swift-database
    
  • Proyecto de Swift compilado con xcodebuild:

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

    Puedes pasar las opciones archive y test a xcodebuild. Sin embargo, se recomienda el comando estándar xcodebuild , ya que debe ser el más rápido y debe ser todo lo que CodeQL requiere para un examen correcto.

  • Proyecto de Swift compilado con un script de compilación personalizado:

    codeql database create -l swift -c "./scripts/build.sh" swift-database
    
  • Proyecto compilado con 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
    

Nota:

La compilación de Bazel para Go no está soportada actualmente.

  • Proyecto compilado con un script de compilación personalizado:

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

Este comando ejecuta un script personalizado que contiene todos los comandos necesarios para compilar el proyecto.

Uso del seguimiento indirecto de la compilación

Si los CodeQL CLI autobuilders para lenguajes compilados no funcionan con su flujo de trabajo de CI y no puede envolver las invocaciones de comandos de compilación con codeql database trace-command, puede usar el trazado indirecto de compilación para crear una base de datos CodeQL. A fin de usar el seguimiento indirecto de la compilación, el sistema de CI debe poder establecer variables de entorno personalizadas para cada acción de compilación.

Para crear una CodeQL base de datos con seguimiento indirecto de compilación, ejecute el siguiente comando desde la raíz de desprotección del proyecto:

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

Debe especificar:

  • <database>: una ruta de acceso a la base de datos nueva que se va a crear. Este directorio se creará al ejecutar el comando; no se puede especificar un directorio existente.
  • --begin-tracing: crea scripts que se pueden usar para configurar un entorno en el que se realizará un seguimiento de los comandos de compilación.

Puedes especificar otras opciones para el comando codeql database init con normalidad.

Nota:

Si la compilación se ejecuta en Windows, debe establecer --trace-process-level <number> o --trace-process-name <parent process name> para que la opción apunte a un proceso de CI primario que observará todos los pasos de compilación para el código que se está analizando.

El comando codeql database init dará generará un mensaje:

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

El codeql database init comando crea <database>/temp/tracingEnvironment con archivos que contienen variables de entorno y valores que permitirán CodeQL realizar un seguimiento de una secuencia de pasos de compilación. Estos archivos se denominan start-tracing.{json,sh,bat,ps1}. Usa uno de estos archivos con el mecanismo del sistema de CI a fin de establecer variables de entorno para pasos futuros. Ustedes pueden:

  • Leer el archivo JSON, procesarlo e imprimir variables de entorno en el formato que espera el sistema de CI. Por ejemplo, Azure DevOps espera echo "##vso[task.setvariable variable=NAME]VALUE".
  • O bien, si el sistema de CI conserva el entorno, ejecute el script start-tracing adecuado para establecer las variables CodeQL en el entorno de shell del sistema de CI.

Compila el código; opcionalmente, anula las variables de entorno mediante un script de end-tracing.{json,sh,bat,ps1} del directorio donde se almacenan los scripts de start-tracing; y, después, ejecuta el comando codeql database finalize <database>.

Una vez que haya creado una CodeQL base de datos mediante el seguimiento indirecto de la compilación, puede trabajar con ella como cualquier otra CodeQL base de datos. Por ejemplo, analice la base de datos y cargue los resultados en GitHub si utiliza el análisis de código.

Ejemplo de creación de una CodeQL base de datos mediante el seguimiento indirecto de compilación

Nota:

Si usa canalizaciones de Azure DevOps, la manera más sencilla de crear una base de datos CodeQL es usar GitHub Advanced Security for Azure DevOps. Para obtener documentación, consulte Configure GitHub Advanced Security for Azure DevOps en Microsoft Learn.

En el ejemplo siguiente se muestra cómo puede usar el seguimiento indirecto de compilación en una canalización de Azure DevOps para crear una base de datos 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` ...

Pasos siguientes